comparison sat/memory/memory.py @ 3288:780fb8dd07ef

core (memory/sqlite): new database schema (v9): this new schema brings the new `public_id` column, which will be used to serve files via HTTP, splits `mime_type` in 2 (`media_type` and `media_subtype`) to make indexing/media filtering easier, and fixes indexes for `files` table.
author Goffi <goffi@goffi.org>
date Fri, 29 May 2020 21:50:49 +0200
parents a3639d6d9643
children b56e4c6b13fc
comparison
equal deleted inserted replaced
3287:a4b8c9bcfb57 3288:780fb8dd07ef
20 import os.path 20 import os.path
21 import copy 21 import copy
22 import shortuuid 22 import shortuuid
23 import mimetypes 23 import mimetypes
24 import time 24 import time
25 from pathlib import Path
25 from uuid import uuid4 26 from uuid import uuid4
26 from collections import namedtuple 27 from collections import namedtuple
27 from twisted.python import failure 28 from twisted.python import failure
28 from twisted.internet import defer, reactor, error 29 from twisted.internet import defer, reactor, error
29 from twisted.words.protocols.jabber import jid 30 from twisted.words.protocols.jabber import jid
1291 1292
1292 @defer.inlineCallbacks 1293 @defer.inlineCallbacks
1293 def getFiles( 1294 def getFiles(
1294 self, client, peer_jid, file_id=None, version=None, parent=None, path=None, 1295 self, client, peer_jid, file_id=None, version=None, parent=None, path=None,
1295 type_=None, file_hash=None, hash_algo=None, name=None, namespace=None, 1296 type_=None, file_hash=None, hash_algo=None, name=None, namespace=None,
1296 mime_type=None, owner=None, access=None, projection=None, unique=False, 1297 mime_type=None, public_id=None, owner=None, access=None, projection=None,
1297 perms_to_check=(C.ACCESS_PERM_READ,)): 1298 unique=False, perms_to_check=(C.ACCESS_PERM_READ,)):
1298 """Retrieve files with with given filters 1299 """Retrieve files with with given filters
1299 1300
1300 @param peer_jid(jid.JID, None): jid trying to access the file 1301 @param peer_jid(jid.JID, None): jid trying to access the file
1301 needed to check permission. 1302 needed to check permission.
1302 Use None to ignore permission (perms_to_check must be None too) 1303 Use None to ignore permission (perms_to_check must be None too)
1313 @param file_hash(unicode, None): hash of the file to retrieve 1314 @param file_hash(unicode, None): hash of the file to retrieve
1314 @param hash_algo(unicode, None): algorithm use for file_hash 1315 @param hash_algo(unicode, None): algorithm use for file_hash
1315 @param name(unicode, None): name of the file to retrieve 1316 @param name(unicode, None): name of the file to retrieve
1316 @param namespace(unicode, None): namespace of the files to retrieve 1317 @param namespace(unicode, None): namespace of the files to retrieve
1317 @param mime_type(unicode, None): filter on this mime type 1318 @param mime_type(unicode, None): filter on this mime type
1319 @param public_id(unicode, None): filter on this public id
1318 @param owner(jid.JID, None): if not None, only get files from this owner 1320 @param owner(jid.JID, None): if not None, only get files from this owner
1319 @param access(dict, None): get file with given access (see [setFile]) 1321 @param access(dict, None): get file with given access (see [setFile])
1320 @param projection(list[unicode], None): name of columns to retrieve 1322 @param projection(list[unicode], None): name of columns to retrieve
1321 None to retrieve all 1323 None to retrieve all
1322 @param unique(bool): if True will remove duplicates 1324 @param unique(bool): if True will remove duplicates
1367 file_hash=file_hash, 1369 file_hash=file_hash,
1368 hash_algo=hash_algo, 1370 hash_algo=hash_algo,
1369 name=name, 1371 name=name,
1370 namespace=namespace, 1372 namespace=namespace,
1371 mime_type=mime_type, 1373 mime_type=mime_type,
1374 public_id=public_id,
1372 owner=owner, 1375 owner=owner,
1373 access=access, 1376 access=access,
1374 projection=projection, 1377 projection=projection,
1375 unique=unique, 1378 unique=unique,
1376 ) 1379 )
1387 files.remove(file_data) 1390 files.remove(file_data)
1388 defer.returnValue(files) 1391 defer.returnValue(files)
1389 1392
1390 @defer.inlineCallbacks 1393 @defer.inlineCallbacks
1391 def setFile( 1394 def setFile(
1392 self, client, name, file_id=None, version="", parent=None, path=None, 1395 self, client, name, file_id=None, version="", parent=None, path=None,
1393 type_=C.FILE_TYPE_FILE, file_hash=None, hash_algo=None, size=None, 1396 type_=C.FILE_TYPE_FILE, file_hash=None, hash_algo=None, size=None,
1394 namespace=None, mime_type=None, created=None, modified=None, owner=None, 1397 namespace=None, mime_type=None, public_id=None, created=None, modified=None,
1395 access=None, extra=None, peer_jid=None, perms_to_check=(C.ACCESS_PERM_WRITE,) 1398 owner=None, access=None, extra=None, peer_jid=None,
1396 ): 1399 perms_to_check=(C.ACCESS_PERM_WRITE,)
1400 ):
1397 """Set a file metadata 1401 """Set a file metadata
1398 1402
1399 @param name(unicode): basename of the file 1403 @param name(unicode): basename of the file
1400 @param file_id(unicode): unique id of the file 1404 @param file_id(unicode): unique id of the file
1401 @param version(unicode): version of this file 1405 @param version(unicode): version of this file
1409 @param size(int): size in bytes 1413 @param size(int): size in bytes
1410 @param namespace(unicode, None): identifier (human readable is better) to group 1414 @param namespace(unicode, None): identifier (human readable is better) to group
1411 files 1415 files
1412 For instance, namespace could be used to group files in a specific photo album 1416 For instance, namespace could be used to group files in a specific photo album
1413 @param mime_type(unicode): MIME type of the file, or None if not known/guessed 1417 @param mime_type(unicode): MIME type of the file, or None if not known/guessed
1418 @param public_id(unicode): id used to share publicly the file via HTTP
1414 @param created(int): UNIX time of creation 1419 @param created(int): UNIX time of creation
1415 @param modified(int,None): UNIX time of last modification, or None to use 1420 @param modified(int,None): UNIX time of last modification, or None to use
1416 created date 1421 created date
1417 @param owner(jid.JID, None): jid of the owner of the file (mainly useful for 1422 @param owner(jid.JID, None): jid of the owner of the file (mainly useful for
1418 component) 1423 component)
1446 or hash_algo is not None 1451 or hash_algo is not None
1447 and file_hash is None 1452 and file_hash is None
1448 ): 1453 ):
1449 raise ValueError("file_hash and hash_algo must be set at the same time") 1454 raise ValueError("file_hash and hash_algo must be set at the same time")
1450 if mime_type is None: 1455 if mime_type is None:
1451 mime_type, file_encoding = mimetypes.guess_type(name) 1456 mime_type, __ = mimetypes.guess_type(name)
1457 else:
1458 mime_type = mime_type.lower()
1459 if public_id is not None:
1460 assert len(public_id)>0
1452 if created is None: 1461 if created is None:
1453 created = time.time() 1462 created = time.time()
1454 if namespace is not None: 1463 if namespace is not None:
1455 namespace = namespace.strip() or None 1464 namespace = namespace.strip() or None
1456 if type_ == C.FILE_TYPE_DIRECTORY: 1465 if type_ == C.FILE_TYPE_DIRECTORY:
1475 file_id=new_dir_id, 1484 file_id=new_dir_id,
1476 version="", 1485 version="",
1477 parent=parent, 1486 parent=parent,
1478 type_=C.FILE_TYPE_DIRECTORY, 1487 type_=C.FILE_TYPE_DIRECTORY,
1479 namespace=namespace, 1488 namespace=namespace,
1489 public_id=public_id,
1480 created=time.time(), 1490 created=time.time(),
1481 owner=owner, 1491 owner=owner,
1482 access=access, 1492 access=access,
1483 extra={}, 1493 extra={},
1484 ) 1494 )
1496 hash_algo=hash_algo, 1506 hash_algo=hash_algo,
1497 name=name, 1507 name=name,
1498 size=size, 1508 size=size,
1499 namespace=namespace, 1509 namespace=namespace,
1500 mime_type=mime_type, 1510 mime_type=mime_type,
1511 public_id=public_id,
1501 created=created, 1512 created=created,
1502 modified=modified, 1513 modified=modified,
1503 owner=owner, 1514 owner=owner,
1504 access=access, 1515 access=access,
1505 extra=extra, 1516 extra=extra,
1516 Note that the callable must be thread-safe 1527 Note that the callable must be thread-safe
1517 """ 1528 """
1518 return self.storage.fileUpdate(file_id, column, update_cb) 1529 return self.storage.fileUpdate(file_id, column, update_cb)
1519 1530
1520 @defer.inlineCallbacks 1531 @defer.inlineCallbacks
1521 def _deleteFile(self, client, peer_jid, recursive, files_path, file_data): 1532 def _deleteFile(
1533 self,
1534 client,
1535 peer_jid: jid.JID,
1536 recursive: bool,
1537 files_path: Path,
1538 file_data: dict
1539 ):
1522 """Internal method to delete files/directories recursively 1540 """Internal method to delete files/directories recursively
1523 1541
1524 @param peer_jid(jid.JID): entity requesting the deletion (must be owner of files 1542 @param peer_jid(jid.JID): entity requesting the deletion (must be owner of files
1525 to delete) 1543 to delete)
1526 @param recursive(boolean): True if recursive deletion is needed 1544 @param recursive(boolean): True if recursive deletion is needed