Mercurial > libervia-backend
comparison sat/plugins/plugin_comp_file_sharing_management.py @ 3028:ab2696e34d29
Python 3 port:
/!\ this is a huge commit
/!\ starting from this commit, SàT is needs Python 3.6+
/!\ SàT maybe be instable or some feature may not work anymore, this will improve with time
This patch port backend, bridge and frontends to Python 3.
Roughly this has been done this way:
- 2to3 tools has been applied (with python 3.7)
- all references to python2 have been replaced with python3 (notably shebangs)
- fixed files not handled by 2to3 (notably the shell script)
- several manual fixes
- fixed issues reported by Python 3 that where not handled in Python 2
- replaced "async" with "async_" when needed (it's a reserved word from Python 3.7)
- replaced zope's "implements" with @implementer decorator
- temporary hack to handle data pickled in database, as str or bytes may be returned,
to be checked later
- fixed hash comparison for password
- removed some code which is not needed anymore with Python 3
- deactivated some code which needs to be checked (notably certificate validation)
- tested with jp, fixed reported issues until some basic commands worked
- ported Primitivus (after porting dependencies like urwid satext)
- more manual fixes
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 13 Aug 2019 19:08:41 +0200 |
parents | 0bafdbda7f5f |
children | 9d0df638c8b4 |
comparison
equal
deleted
inserted
replaced
3027:ff5bcb12ae60 | 3028:ab2696e34d29 |
---|---|
1 #!/usr/bin/env python2 | 1 #!/usr/bin/env python3 |
2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
3 | 3 |
4 # SAT plugin to detect language (experimental) | 4 # SAT plugin to detect language (experimental) |
5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) | 5 # Copyright (C) 2009-2019 Jérôme Poisson (goffi@goffi.org) |
6 | 6 |
29 | 29 |
30 log = getLogger(__name__) | 30 log = getLogger(__name__) |
31 | 31 |
32 | 32 |
33 PLUGIN_INFO = { | 33 PLUGIN_INFO = { |
34 C.PI_NAME: u"File Sharing Management", | 34 C.PI_NAME: "File Sharing Management", |
35 C.PI_IMPORT_NAME: u"FILE_SHARING_MANAGEMENT", | 35 C.PI_IMPORT_NAME: "FILE_SHARING_MANAGEMENT", |
36 C.PI_MODES: [C.PLUG_MODE_COMPONENT], | 36 C.PI_MODES: [C.PLUG_MODE_COMPONENT], |
37 C.PI_TYPE: u"EXP", | 37 C.PI_TYPE: "EXP", |
38 C.PI_PROTOCOLS: [], | 38 C.PI_PROTOCOLS: [], |
39 C.PI_DEPENDENCIES: [u"XEP-0050", u"XEP-0264"], | 39 C.PI_DEPENDENCIES: ["XEP-0050", "XEP-0264"], |
40 C.PI_RECOMMENDATIONS: [], | 40 C.PI_RECOMMENDATIONS: [], |
41 C.PI_MAIN: u"FileSharingManagement", | 41 C.PI_MAIN: "FileSharingManagement", |
42 C.PI_HANDLER: u"no", | 42 C.PI_HANDLER: "no", |
43 C.PI_DESCRIPTION: _( | 43 C.PI_DESCRIPTION: _( |
44 u"Experimental handling of file management for file sharing. This plugins allows " | 44 "Experimental handling of file management for file sharing. This plugins allows " |
45 u"to change permissions of stored files/directories or remove them." | 45 "to change permissions of stored files/directories or remove them." |
46 ), | 46 ), |
47 } | 47 } |
48 | 48 |
49 NS_FILE_MANAGEMENT = u"https://salut-a-toi.org/protocol/file-management:0" | 49 NS_FILE_MANAGEMENT = "https://salut-a-toi.org/protocol/file-management:0" |
50 NS_FILE_MANAGEMENT_PERM = u"https://salut-a-toi.org/protocol/file-management:0#perm" | 50 NS_FILE_MANAGEMENT_PERM = "https://salut-a-toi.org/protocol/file-management:0#perm" |
51 NS_FILE_MANAGEMENT_DELETE = u"https://salut-a-toi.org/protocol/file-management:0#delete" | 51 NS_FILE_MANAGEMENT_DELETE = "https://salut-a-toi.org/protocol/file-management:0#delete" |
52 NS_FILE_MANAGEMENT_THUMB = u"https://salut-a-toi.org/protocol/file-management:0#thumb" | 52 NS_FILE_MANAGEMENT_THUMB = "https://salut-a-toi.org/protocol/file-management:0#thumb" |
53 | 53 |
54 | 54 |
55 class WorkflowError(Exception): | 55 class WorkflowError(Exception): |
56 """Raised when workflow can't be completed""" | 56 """Raised when workflow can't be completed""" |
57 | 57 |
66 class FileSharingManagement(object): | 66 class FileSharingManagement(object): |
67 # This is a temporary way (Q&D) to handle stored files, a better way (using pubsub | 67 # This is a temporary way (Q&D) to handle stored files, a better way (using pubsub |
68 # syntax?) should be elaborated and proposed as a standard. | 68 # syntax?) should be elaborated and proposed as a standard. |
69 | 69 |
70 def __init__(self, host): | 70 def __init__(self, host): |
71 log.info(_(u"File Sharing Management plugin initialization")) | 71 log.info(_("File Sharing Management plugin initialization")) |
72 self.host = host | 72 self.host = host |
73 self._c = host.plugins["XEP-0050"] | 73 self._c = host.plugins["XEP-0050"] |
74 self._t = host.plugins["XEP-0264"] | 74 self._t = host.plugins["XEP-0264"] |
75 self.files_path = host.getLocalPath(None, C.FILES_DIR, profile=False) | 75 self.files_path = host.getLocalPath(None, C.FILES_DIR, profile=False) |
76 | 76 |
77 def profileConnected(self, client): | 77 def profileConnected(self, client): |
78 self._c.addAdHocCommand( | 78 self._c.addAdHocCommand( |
79 client, self._onChangeFile, u"Change Permissions of File(s)", | 79 client, self._onChangeFile, "Change Permissions of File(s)", |
80 node=NS_FILE_MANAGEMENT_PERM, | 80 node=NS_FILE_MANAGEMENT_PERM, |
81 allowed_magics=C.ENTITY_ALL, | 81 allowed_magics=C.ENTITY_ALL, |
82 ) | 82 ) |
83 self._c.addAdHocCommand( | 83 self._c.addAdHocCommand( |
84 client, self._onDeleteFile, u"Delete File(s)", | 84 client, self._onDeleteFile, "Delete File(s)", |
85 node=NS_FILE_MANAGEMENT_DELETE, | 85 node=NS_FILE_MANAGEMENT_DELETE, |
86 allowed_magics=C.ENTITY_ALL, | 86 allowed_magics=C.ENTITY_ALL, |
87 ) | 87 ) |
88 self._c.addAdHocCommand( | 88 self._c.addAdHocCommand( |
89 client, self._onGenThumbnails, u"Generate Thumbnails", | 89 client, self._onGenThumbnails, "Generate Thumbnails", |
90 node=NS_FILE_MANAGEMENT_THUMB, | 90 node=NS_FILE_MANAGEMENT_THUMB, |
91 allowed_magics=C.ENTITY_ALL, | 91 allowed_magics=C.ENTITY_ALL, |
92 ) | 92 ) |
93 | 93 |
94 def _err(self, reason): | 94 def _err(self, reason): |
107 """Create the form to select the file to use | 107 """Create the form to select the file to use |
108 | 108 |
109 @return (tuple): arguments to use in defer.returnValue | 109 @return (tuple): arguments to use in defer.returnValue |
110 """ | 110 """ |
111 status = self._c.STATUS.EXECUTING | 111 status = self._c.STATUS.EXECUTING |
112 form = data_form.Form("form", title=u"File Management", | 112 form = data_form.Form("form", title="File Management", |
113 formNamespace=NS_FILE_MANAGEMENT) | 113 formNamespace=NS_FILE_MANAGEMENT) |
114 | 114 |
115 field = data_form.Field( | 115 field = data_form.Field( |
116 "text-single", "path", required=True | 116 "text-single", "path", required=True |
117 ) | 117 ) |
134 @return (D(dict)): found file data | 134 @return (D(dict)): found file data |
135 @raise WorkflowError: something is wrong | 135 @raise WorkflowError: something is wrong |
136 """ | 136 """ |
137 fields = command_form.fields | 137 fields = command_form.fields |
138 try: | 138 try: |
139 path = fields[u'path'].value.strip() | 139 path = fields['path'].value.strip() |
140 namespace = fields[u'namespace'].value or None | 140 namespace = fields['namespace'].value or None |
141 except KeyError: | 141 except KeyError: |
142 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) | 142 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) |
143 | 143 |
144 if not path: | 144 if not path: |
145 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) | 145 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) |
146 | 146 |
147 requestor = session_data[u'requestor'] | 147 requestor = session_data['requestor'] |
148 requestor_bare = requestor.userhostJID() | 148 requestor_bare = requestor.userhostJID() |
149 path = path.rstrip(u'/') | 149 path = path.rstrip('/') |
150 parent_path, basename = os.path.split(path) | 150 parent_path, basename = os.path.split(path) |
151 | 151 |
152 # TODO: if parent_path and basename are empty, we ask for root directory | 152 # TODO: if parent_path and basename are empty, we ask for root directory |
153 # this must be managed | 153 # this must be managed |
154 | 154 |
156 found_files = yield self.host.memory.getFiles( | 156 found_files = yield self.host.memory.getFiles( |
157 client, requestor_bare, path=parent_path, name=basename, | 157 client, requestor_bare, path=parent_path, name=basename, |
158 namespace=namespace) | 158 namespace=namespace) |
159 found_file = found_files[0] | 159 found_file = found_files[0] |
160 except (exceptions.NotFound, IndexError): | 160 except (exceptions.NotFound, IndexError): |
161 raise WorkflowError(self._err(_(u"file not found"))) | 161 raise WorkflowError(self._err(_("file not found"))) |
162 except exceptions.PermissionError: | 162 except exceptions.PermissionError: |
163 raise WorkflowError(self._err(_(u"forbidden"))) | 163 raise WorkflowError(self._err(_("forbidden"))) |
164 | 164 |
165 if found_file['owner'] != requestor_bare: | 165 if found_file['owner'] != requestor_bare: |
166 # only owner can manage files | 166 # only owner can manage files |
167 log.warning(_(u"Only owner can manage files")) | 167 log.warning(_("Only owner can manage files")) |
168 raise WorkflowError(self._err(_(u"forbidden"))) | 168 raise WorkflowError(self._err(_("forbidden"))) |
169 | 169 |
170 session_data[u'found_file'] = found_file | 170 session_data['found_file'] = found_file |
171 session_data[u'namespace'] = namespace | 171 session_data['namespace'] = namespace |
172 defer.returnValue(found_file) | 172 defer.returnValue(found_file) |
173 | 173 |
174 def _updateReadPermission(self, access, allowed_jids): | 174 def _updateReadPermission(self, access, allowed_jids): |
175 if not allowed_jids: | 175 if not allowed_jids: |
176 if C.ACCESS_PERM_READ in access: | 176 if C.ACCESS_PERM_READ in access: |
177 del access[C.ACCESS_PERM_READ] | 177 del access[C.ACCESS_PERM_READ] |
178 elif allowed_jids == u'PUBLIC': | 178 elif allowed_jids == 'PUBLIC': |
179 access[C.ACCESS_PERM_READ] = { | 179 access[C.ACCESS_PERM_READ] = { |
180 u"type": C.ACCESS_TYPE_PUBLIC | 180 "type": C.ACCESS_TYPE_PUBLIC |
181 } | 181 } |
182 else: | 182 else: |
183 access[C.ACCESS_PERM_READ] = { | 183 access[C.ACCESS_PERM_READ] = { |
184 u"type": C.ACCESS_TYPE_WHITELIST, | 184 "type": C.ACCESS_TYPE_WHITELIST, |
185 u"jids": [j.full() for j in allowed_jids] | 185 "jids": [j.full() for j in allowed_jids] |
186 } | 186 } |
187 | 187 |
188 @defer.inlineCallbacks | 188 @defer.inlineCallbacks |
189 def _updateDir(self, client, requestor, namespace, file_data, allowed_jids): | 189 def _updateDir(self, client, requestor, namespace, file_data, allowed_jids): |
190 """Recursively update permission of a directory and all subdirectories | 190 """Recursively update permission of a directory and all subdirectories |
191 | 191 |
192 @param file_data(dict): metadata of the file | 192 @param file_data(dict): metadata of the file |
193 @param allowed_jids(list[jid.JID]): list of entities allowed to read the file | 193 @param allowed_jids(list[jid.JID]): list of entities allowed to read the file |
194 """ | 194 """ |
195 assert file_data[u'type'] == C.FILE_TYPE_DIRECTORY | 195 assert file_data['type'] == C.FILE_TYPE_DIRECTORY |
196 files_data = yield self.host.memory.getFiles( | 196 files_data = yield self.host.memory.getFiles( |
197 client, requestor, parent=file_data[u'id'], namespace=namespace) | 197 client, requestor, parent=file_data['id'], namespace=namespace) |
198 | 198 |
199 for file_data in files_data: | 199 for file_data in files_data: |
200 if not file_data[u'access'].get(C.ACCESS_PERM_READ, {}): | 200 if not file_data['access'].get(C.ACCESS_PERM_READ, {}): |
201 log.debug(u"setting {perm} read permission for {name}".format( | 201 log.debug("setting {perm} read permission for {name}".format( |
202 perm=allowed_jids, name=file_data[u'name'])) | 202 perm=allowed_jids, name=file_data['name'])) |
203 yield self.host.memory.fileUpdate( | 203 yield self.host.memory.fileUpdate( |
204 file_data[u'id'], u'access', | 204 file_data['id'], 'access', |
205 partial(self._updateReadPermission, allowed_jids=allowed_jids)) | 205 partial(self._updateReadPermission, allowed_jids=allowed_jids)) |
206 if file_data[u'type'] == C.FILE_TYPE_DIRECTORY: | 206 if file_data['type'] == C.FILE_TYPE_DIRECTORY: |
207 yield self._updateDir(client, requestor, namespace, file_data, u'PUBLIC') | 207 yield self._updateDir(client, requestor, namespace, file_data, 'PUBLIC') |
208 | 208 |
209 @defer.inlineCallbacks | 209 @defer.inlineCallbacks |
210 def _onChangeFile(self, client, command_elt, session_data, action, node): | 210 def _onChangeFile(self, client, command_elt, session_data, action, node): |
211 try: | 211 try: |
212 x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next() | 212 x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x")) |
213 command_form = data_form.Form.fromElement(x_elt) | 213 command_form = data_form.Form.fromElement(x_elt) |
214 except StopIteration: | 214 except StopIteration: |
215 command_form = None | 215 command_form = None |
216 | 216 |
217 found_file = session_data.get('found_file') | 217 found_file = session_data.get('found_file') |
218 requestor = session_data[u'requestor'] | 218 requestor = session_data['requestor'] |
219 requestor_bare = requestor.userhostJID() | 219 requestor_bare = requestor.userhostJID() |
220 | 220 |
221 if command_form is None or len(command_form.fields) == 0: | 221 if command_form is None or len(command_form.fields) == 0: |
222 # root request | 222 # root request |
223 defer.returnValue(self._getRootArgs()) | 223 defer.returnValue(self._getRootArgs()) |
228 found_file = yield self._getFileData(client, session_data, command_form) | 228 found_file = yield self._getFileData(client, session_data, command_form) |
229 except WorkflowError as e: | 229 except WorkflowError as e: |
230 defer.returnValue(e.err_args) | 230 defer.returnValue(e.err_args) |
231 | 231 |
232 # management request | 232 # management request |
233 if found_file[u'type'] == C.FILE_TYPE_DIRECTORY: | 233 if found_file['type'] == C.FILE_TYPE_DIRECTORY: |
234 instructions = D_(u"Please select permissions for this directory") | 234 instructions = D_("Please select permissions for this directory") |
235 else: | 235 else: |
236 instructions = D_(u"Please select permissions for this file") | 236 instructions = D_("Please select permissions for this file") |
237 | 237 |
238 form = data_form.Form("form", title=u"File Management", | 238 form = data_form.Form("form", title="File Management", |
239 instructions=[instructions], | 239 instructions=[instructions], |
240 formNamespace=NS_FILE_MANAGEMENT) | 240 formNamespace=NS_FILE_MANAGEMENT) |
241 field = data_form.Field( | 241 field = data_form.Field( |
242 "text-multi", "read_allowed", required=False, | 242 "text-multi", "read_allowed", required=False, |
243 desc=u'list of jids allowed to read this file (beside yourself), or ' | 243 desc='list of jids allowed to read this file (beside yourself), or ' |
244 u'"PUBLIC" to let a public access' | 244 '"PUBLIC" to let a public access' |
245 ) | 245 ) |
246 read_access = found_file[u"access"].get(C.ACCESS_PERM_READ, {}) | 246 read_access = found_file["access"].get(C.ACCESS_PERM_READ, {}) |
247 access_type = read_access.get(u'type', C.ACCESS_TYPE_WHITELIST) | 247 access_type = read_access.get('type', C.ACCESS_TYPE_WHITELIST) |
248 if access_type == C.ACCESS_TYPE_PUBLIC: | 248 if access_type == C.ACCESS_TYPE_PUBLIC: |
249 field.values = [u'PUBLIC'] | 249 field.values = ['PUBLIC'] |
250 else: | 250 else: |
251 field.values = read_access.get('jids', []) | 251 field.values = read_access.get('jids', []) |
252 form.addField(field) | 252 form.addField(field) |
253 if found_file[u'type'] == C.FILE_TYPE_DIRECTORY: | 253 if found_file['type'] == C.FILE_TYPE_DIRECTORY: |
254 field = data_form.Field( | 254 field = data_form.Field( |
255 "boolean", "recursive", value=False, required=False, | 255 "boolean", "recursive", value=False, required=False, |
256 desc=u"Files under it will be made public to follow this dir " | 256 desc="Files under it will be made public to follow this dir " |
257 u"permission (only if they don't have already a permission set)." | 257 "permission (only if they don't have already a permission set)." |
258 ) | 258 ) |
259 form.addField(field) | 259 form.addField(field) |
260 | 260 |
261 status = self._c.STATUS.EXECUTING | 261 status = self._c.STATUS.EXECUTING |
262 payload = form.toElement() | 262 payload = form.toElement() |
267 try: | 267 try: |
268 read_allowed = command_form.fields['read_allowed'] | 268 read_allowed = command_form.fields['read_allowed'] |
269 except KeyError: | 269 except KeyError: |
270 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) | 270 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) |
271 | 271 |
272 if read_allowed.value == u'PUBLIC': | 272 if read_allowed.value == 'PUBLIC': |
273 allowed_jids = u'PUBLIC' | 273 allowed_jids = 'PUBLIC' |
274 elif read_allowed.value.strip() == u'': | 274 elif read_allowed.value.strip() == '': |
275 allowed_jids = None | 275 allowed_jids = None |
276 else: | 276 else: |
277 try: | 277 try: |
278 allowed_jids = [jid.JID(v.strip()) for v in read_allowed.values | 278 allowed_jids = [jid.JID(v.strip()) for v in read_allowed.values |
279 if v.strip()] | 279 if v.strip()] |
280 except RuntimeError as e: | 280 except RuntimeError as e: |
281 log.warning(_(u"Can't use read_allowed values: {reason}").format( | 281 log.warning(_("Can't use read_allowed values: {reason}").format( |
282 reason=e)) | 282 reason=e)) |
283 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) | 283 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) |
284 | 284 |
285 if found_file[u'type'] == C.FILE_TYPE_FILE: | 285 if found_file['type'] == C.FILE_TYPE_FILE: |
286 yield self.host.memory.fileUpdate( | 286 yield self.host.memory.fileUpdate( |
287 found_file[u'id'], u'access', | 287 found_file['id'], 'access', |
288 partial(self._updateReadPermission, allowed_jids=allowed_jids)) | 288 partial(self._updateReadPermission, allowed_jids=allowed_jids)) |
289 else: | 289 else: |
290 try: | 290 try: |
291 recursive = command_form.fields['recursive'] | 291 recursive = command_form.fields['recursive'] |
292 except KeyError: | 292 except KeyError: |
293 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) | 293 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) |
294 yield self.host.memory.fileUpdate( | 294 yield self.host.memory.fileUpdate( |
295 found_file[u'id'], u'access', | 295 found_file['id'], 'access', |
296 partial(self._updateReadPermission, allowed_jids=allowed_jids)) | 296 partial(self._updateReadPermission, allowed_jids=allowed_jids)) |
297 if recursive: | 297 if recursive: |
298 # we set all file under the directory as public (if they haven't | 298 # we set all file under the directory as public (if they haven't |
299 # already a permission set), so allowed entities of root directory | 299 # already a permission set), so allowed entities of root directory |
300 # can read them. | 300 # can read them. |
301 namespace = session_data[u'namespace'] | 301 namespace = session_data['namespace'] |
302 yield self._updateDir( | 302 yield self._updateDir( |
303 client, requestor_bare, namespace, found_file, u'PUBLIC') | 303 client, requestor_bare, namespace, found_file, 'PUBLIC') |
304 | 304 |
305 # job done, we can end the session | 305 # job done, we can end the session |
306 status = self._c.STATUS.COMPLETED | 306 status = self._c.STATUS.COMPLETED |
307 payload = None | 307 payload = None |
308 note = (self._c.NOTE.INFO, _(u"management session done")) | 308 note = (self._c.NOTE.INFO, _("management session done")) |
309 defer.returnValue((payload, status, None, note)) | 309 defer.returnValue((payload, status, None, note)) |
310 | 310 |
311 @defer.inlineCallbacks | 311 @defer.inlineCallbacks |
312 def _onDeleteFile(self, client, command_elt, session_data, action, node): | 312 def _onDeleteFile(self, client, command_elt, session_data, action, node): |
313 try: | 313 try: |
314 x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next() | 314 x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x")) |
315 command_form = data_form.Form.fromElement(x_elt) | 315 command_form = data_form.Form.fromElement(x_elt) |
316 except StopIteration: | 316 except StopIteration: |
317 command_form = None | 317 command_form = None |
318 | 318 |
319 found_file = session_data.get('found_file') | 319 found_file = session_data.get('found_file') |
320 requestor = session_data[u'requestor'] | 320 requestor = session_data['requestor'] |
321 requestor_bare = requestor.userhostJID() | 321 requestor_bare = requestor.userhostJID() |
322 | 322 |
323 if command_form is None or len(command_form.fields) == 0: | 323 if command_form is None or len(command_form.fields) == 0: |
324 # root request | 324 # root request |
325 defer.returnValue(self._getRootArgs()) | 325 defer.returnValue(self._getRootArgs()) |
328 # file selected, we need confirmation before actually deleting | 328 # file selected, we need confirmation before actually deleting |
329 try: | 329 try: |
330 found_file = yield self._getFileData(client, session_data, command_form) | 330 found_file = yield self._getFileData(client, session_data, command_form) |
331 except WorkflowError as e: | 331 except WorkflowError as e: |
332 defer.returnValue(e.err_args) | 332 defer.returnValue(e.err_args) |
333 if found_file[u'type'] == C.FILE_TYPE_DIRECTORY: | 333 if found_file['type'] == C.FILE_TYPE_DIRECTORY: |
334 msg = D_(u"Are you sure to delete directory {name} and all files and " | 334 msg = D_("Are you sure to delete directory {name} and all files and " |
335 u"directories under it?").format(name=found_file[u'name']) | 335 "directories under it?").format(name=found_file['name']) |
336 else: | 336 else: |
337 msg = D_(u"Are you sure to delete file {name}?" | 337 msg = D_("Are you sure to delete file {name}?" |
338 .format(name=found_file[u'name'])) | 338 .format(name=found_file['name'])) |
339 form = data_form.Form("form", title=u"File Management", | 339 form = data_form.Form("form", title="File Management", |
340 instructions = [msg], | 340 instructions = [msg], |
341 formNamespace=NS_FILE_MANAGEMENT) | 341 formNamespace=NS_FILE_MANAGEMENT) |
342 field = data_form.Field( | 342 field = data_form.Field( |
343 "boolean", "confirm", value=False, required=True, | 343 "boolean", "confirm", value=False, required=True, |
344 desc=u"check this box to confirm" | 344 desc="check this box to confirm" |
345 ) | 345 ) |
346 form.addField(field) | 346 form.addField(field) |
347 status = self._c.STATUS.EXECUTING | 347 status = self._c.STATUS.EXECUTING |
348 payload = form.toElement() | 348 payload = form.toElement() |
349 defer.returnValue((payload, status, None, None)) | 349 defer.returnValue((payload, status, None, None)) |
355 except KeyError: | 355 except KeyError: |
356 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) | 356 self._c.adHocError(self._c.ERROR.BAD_PAYLOAD) |
357 if not confirmed: | 357 if not confirmed: |
358 note = None | 358 note = None |
359 else: | 359 else: |
360 recursive = found_file[u'type'] == C.FILE_TYPE_DIRECTORY | 360 recursive = found_file['type'] == C.FILE_TYPE_DIRECTORY |
361 yield self.host.memory.fileDelete( | 361 yield self.host.memory.fileDelete( |
362 client, requestor_bare, found_file[u'id'], recursive) | 362 client, requestor_bare, found_file['id'], recursive) |
363 note = (self._c.NOTE.INFO, _(u"file deleted")) | 363 note = (self._c.NOTE.INFO, _("file deleted")) |
364 status = self._c.STATUS.COMPLETED | 364 status = self._c.STATUS.COMPLETED |
365 payload = None | 365 payload = None |
366 defer.returnValue((payload, status, None, note)) | 366 defer.returnValue((payload, status, None, note)) |
367 | 367 |
368 def _updateThumbs(self, extra, thumbnails): | 368 def _updateThumbs(self, extra, thumbnails): |
372 def _genThumbs(self, client, requestor, namespace, file_data): | 372 def _genThumbs(self, client, requestor, namespace, file_data): |
373 """Recursively generate thumbnails | 373 """Recursively generate thumbnails |
374 | 374 |
375 @param file_data(dict): metadata of the file | 375 @param file_data(dict): metadata of the file |
376 """ | 376 """ |
377 if file_data[u'type'] == C.FILE_TYPE_DIRECTORY: | 377 if file_data['type'] == C.FILE_TYPE_DIRECTORY: |
378 sub_files_data = yield self.host.memory.getFiles( | 378 sub_files_data = yield self.host.memory.getFiles( |
379 client, requestor, parent=file_data[u'id'], namespace=namespace) | 379 client, requestor, parent=file_data['id'], namespace=namespace) |
380 for sub_file_data in sub_files_data: | 380 for sub_file_data in sub_files_data: |
381 yield self._genThumbs(client, requestor, namespace, sub_file_data) | 381 yield self._genThumbs(client, requestor, namespace, sub_file_data) |
382 | 382 |
383 elif file_data[u'type'] == C.FILE_TYPE_FILE: | 383 elif file_data['type'] == C.FILE_TYPE_FILE: |
384 mime_type = file_data[u'mime_type'] | 384 mime_type = file_data['mime_type'] |
385 file_path = os.path.join(self.files_path, file_data[u'file_hash']) | 385 file_path = os.path.join(self.files_path, file_data['file_hash']) |
386 if mime_type is not None and mime_type.startswith(u"image"): | 386 if mime_type is not None and mime_type.startswith("image"): |
387 thumbnails = [] | 387 thumbnails = [] |
388 | 388 |
389 for max_thumb_size in (self._t.SIZE_SMALL, self._t.SIZE_MEDIUM): | 389 for max_thumb_size in (self._t.SIZE_SMALL, self._t.SIZE_MEDIUM): |
390 try: | 390 try: |
391 thumb_size, thumb_id = yield self._t.generateThumbnail( | 391 thumb_size, thumb_id = yield self._t.generateThumbnail( |
393 max_thumb_size, | 393 max_thumb_size, |
394 # we keep thumbnails for 6 months | 394 # we keep thumbnails for 6 months |
395 60 * 60 * 24 * 31 * 6, | 395 60 * 60 * 24 * 31 * 6, |
396 ) | 396 ) |
397 except Exception as e: | 397 except Exception as e: |
398 log.warning(_(u"Can't create thumbnail: {reason}") | 398 log.warning(_("Can't create thumbnail: {reason}") |
399 .format(reason=e)) | 399 .format(reason=e)) |
400 break | 400 break |
401 thumbnails.append({u"id": thumb_id, u"size": thumb_size}) | 401 thumbnails.append({"id": thumb_id, "size": thumb_size}) |
402 | 402 |
403 yield self.host.memory.fileUpdate( | 403 yield self.host.memory.fileUpdate( |
404 file_data[u'id'], u'extra', | 404 file_data['id'], 'extra', |
405 partial(self._updateThumbs, thumbnails=thumbnails)) | 405 partial(self._updateThumbs, thumbnails=thumbnails)) |
406 | 406 |
407 log.info(u"thumbnails for [{file_name}] generated" | 407 log.info("thumbnails for [{file_name}] generated" |
408 .format(file_name=file_data[u'name'])) | 408 .format(file_name=file_data['name'])) |
409 | 409 |
410 else: | 410 else: |
411 log.warning(u"unmanaged file type: {type_}".format(type_=file_data[u'type'])) | 411 log.warning("unmanaged file type: {type_}".format(type_=file_data['type'])) |
412 | 412 |
413 @defer.inlineCallbacks | 413 @defer.inlineCallbacks |
414 def _onGenThumbnails(self, client, command_elt, session_data, action, node): | 414 def _onGenThumbnails(self, client, command_elt, session_data, action, node): |
415 try: | 415 try: |
416 x_elt = command_elt.elements(data_form.NS_X_DATA, "x").next() | 416 x_elt = next(command_elt.elements(data_form.NS_X_DATA, "x")) |
417 command_form = data_form.Form.fromElement(x_elt) | 417 command_form = data_form.Form.fromElement(x_elt) |
418 except StopIteration: | 418 except StopIteration: |
419 command_form = None | 419 command_form = None |
420 | 420 |
421 found_file = session_data.get('found_file') | 421 found_file = session_data.get('found_file') |
422 requestor = session_data[u'requestor'] | 422 requestor = session_data['requestor'] |
423 | 423 |
424 if command_form is None or len(command_form.fields) == 0: | 424 if command_form is None or len(command_form.fields) == 0: |
425 # root request | 425 # root request |
426 defer.returnValue(self._getRootArgs()) | 426 defer.returnValue(self._getRootArgs()) |
427 | 427 |
430 try: | 430 try: |
431 found_file = yield self._getFileData(client, session_data, command_form) | 431 found_file = yield self._getFileData(client, session_data, command_form) |
432 except WorkflowError as e: | 432 except WorkflowError as e: |
433 defer.returnValue(e.err_args) | 433 defer.returnValue(e.err_args) |
434 | 434 |
435 log.info(u"Generating thumbnails as requested") | 435 log.info("Generating thumbnails as requested") |
436 yield self._genThumbs(client, requestor, found_file[u'namespace'], found_file) | 436 yield self._genThumbs(client, requestor, found_file['namespace'], found_file) |
437 | 437 |
438 # job done, we can end the session | 438 # job done, we can end the session |
439 status = self._c.STATUS.COMPLETED | 439 status = self._c.STATUS.COMPLETED |
440 payload = None | 440 payload = None |
441 note = (self._c.NOTE.INFO, _(u"thumbnails generated")) | 441 note = (self._c.NOTE.INFO, _("thumbnails generated")) |
442 defer.returnValue((payload, status, None, note)) | 442 defer.returnValue((payload, status, None, note)) |