def __init__(self, drive_guid=None, filename=None, version=None): """Construct an Location. This uses the GUID of the drive to identify the drive, and then (optionally) the name of the file in the drive, and then the specific version. The drive GUID has the format {service_uid}/{drive_uid} If the filename is not supplied, then this locates the drive itself. If a version is not supplied, then this locates the latest version of the file """ self._drive_guid = drive_guid self._encoded_filename = None self._filename = None self._version = None if self._drive_guid is not None: self._filename = filename self._version = version if self._filename is not None: from Acquire.ObjectStore import string_to_encoded \ as _string_to_encoded self._encoded_filename = _string_to_encoded(self._filename) else: self._encoded_filename = None
def _root(self): """Return the root key for this group in the object store Returns: string: Root key for group """ from Acquire.ObjectStore import string_to_encoded \ as _string_to_encoded return "accounting/account_groups/%s" % \ _string_to_encoded(self._group)
def _account_key(self, name): """Return the key for the account called 'name' in this group Args: name (str): Name of the account Returns: str: Key for the account 'name' """ from Acquire.ObjectStore import string_to_encoded \ as _string_to_encoded return "%s/%s" % (self._root(), _string_to_encoded(str(name)))
def __init__(self, symmetric_key=None, auto_generate=True): """Construct the key either from a passed key, or by generating a new key. The passed key will be converted into a URL-safe base64-encoded 32byte key """ if symmetric_key is not None: from Acquire.Crypto import Hash as _Hash from Acquire.ObjectStore import string_to_encoded \ as _string_to_encoded self._symkey = _string_to_encoded( _Hash.md5(symmetric_key)).encode("utf-8") else: if auto_generate: self._symkey = _generate_symmetric_key()
def _encode_username(username): """This function returns an encoded (sanitised) version of the username. This will ensure that the username is valid (must be between 3 and 50 characters). The sanitised username is the encoded version, meaning that a user can use a unicode (emoji) username if they so desire """ if username is None: return None if len(username) < 3 or len(username) > 150: from Acquire.Identity import UsernameError raise UsernameError( "The username must be between 3 and 150 characters!") from Acquire.ObjectStore import string_to_encoded \ as _string_to_encoded return _string_to_encoded(username)
def _account_key(self, name): """Return the key for the account called 'name' in this group""" return "%s/%s" % (self._root(), _string_to_encoded(str(name)))
def _root(self): """Return the root key for this group in the object store""" return "account_groups/%s" % _string_to_encoded(self._group)
def _get_key_for_url(self, service_url): from Acquire.ObjectStore import string_to_encoded \ as _string_to_encoded return "%s/url/%s" % (_registry_key, _string_to_encoded(service_url))
def _get_root_key_for_domain(self, domain): from Acquire.ObjectStore import string_to_encoded \ as _string_to_encoded return "%s/domain/%s" % (_registry_key, _string_to_encoded(domain))
def list_files(self, authorisation=None, par=None, identifiers=None, include_metadata=False, dir=None, filename=None): """Return the list of FileMeta data for the files contained in this Drive. The passed authorisation is needed in case the list contents of this drive is not public. If 'dir' is specified, then only search for files in 'dir'. If 'filename' is specified, then only search for the file called 'filename' """ (drive_acl, identifiers) = self._resolve_acl(authorisation=authorisation, resource="list_files", par=par, identifiers=identifiers) if par is not None: if par.location().is_file(): dir = None filename = par.location().filename() elif not par.location().is_drive(): raise PermissionError( "You do not have permission to read the Drive") if not drive_acl.is_readable(): raise PermissionError( "You don't have permission to read this Drive") from Acquire.ObjectStore import ObjectStore as _ObjectStore from Acquire.ObjectStore import encoded_to_string as _encoded_to_string from Acquire.ObjectStore import string_to_encoded as _string_to_encoded from Acquire.Storage import FileMeta as _FileMeta metadata_bucket = self._get_metadata_bucket() if filename is not None: if dir is not None: filename = "%s/%s" % (dir, filename) key = "%s/%s/%s" % (_fileinfo_root, self._drive_uid, _string_to_encoded(filename)) names = [key] elif dir is not None: while dir.endswith("/"): dir = dir[0:-1] encoded_dir = _string_to_encoded(dir) while encoded_dir.endswith("="): encoded_dir = encoded_dir[0:-1] # remove the last two characters, as sometime uuencoding # will change the last characters so they don't match if len(encoded_dir) > 2: encoded_dir = encoded_dir[0:-2] else: encoded_dir = "" key = "%s/%s/%s" % (_fileinfo_root, self._drive_uid, encoded_dir) all_names = _ObjectStore.get_all_object_names(metadata_bucket, key) names = [] dir = "%s/" % dir for name in all_names: decoded_name = _encoded_to_string(name.split("/")[-1]) if decoded_name.startswith(dir): names.append(name) else: key = "%s/%s" % (_fileinfo_root, self._drive_uid) names = _ObjectStore.get_all_object_names(metadata_bucket, key) files = [] if include_metadata: # we need to load all of the metadata info for this file to # return to the user from Acquire.Storage import FileInfo as _FileInfo for name in names: try: data = _ObjectStore.get_object_from_json( metadata_bucket, name) fileinfo = _FileInfo.from_data(data, identifiers=identifiers, upstream=drive_acl) filemeta = fileinfo.get_filemeta() file_acl = filemeta.acl() if file_acl.is_readable() or file_acl.is_writeable(): files.append(filemeta) except: pass else: for name in names: filename = _encoded_to_string(name.split("/")[-1]) files.append(_FileMeta(filename=filename)) return files
def _get_subdrive(self, drive_uid, name, autocreate=True): """Return the DriveInfo for the Drive that the user has called 'name' in the drive with UID 'drive_uid'. If 'autocreate' is True then this drive is automatically created if it does not exist. """ if self.is_null(): raise PermissionError( "You cannot get a DriveInfo from a null UserDrives") from Acquire.ObjectStore import string_to_filepath_parts \ as _string_to_filepath_parts parts = _string_to_filepath_parts(name) if len(parts) != 1: raise ValueError("The passed drive name '%s' is not valid!" % name) from Acquire.Service import get_service_account_bucket \ as _get_service_account_bucket from Acquire.ObjectStore import ObjectStore as _ObjectStore from Acquire.ObjectStore import string_to_encoded as _string_to_encoded encoded_name = _string_to_encoded(name) bucket = _get_service_account_bucket() drive_key = "%s/%s/%s/%s" % (_subdrives_root, self._user_guid, drive_uid, encoded_name) try: drive_uid = _ObjectStore.get_string_object(bucket, drive_key) except: drive_uid = None if drive_uid is not None: from Acquire.Storage import DriveInfo as _DriveInfo drive = _DriveInfo(drive_uid=drive_uid, identifiers=self._identifiers, is_authorised=self._is_authorised) else: drive = None if drive is None: if self._is_authorised and autocreate: # create a new UID for the drive and write this to the # object store from Acquire.ObjectStore import create_uuid as _create_uuid drive_uid = _create_uuid() drive_uid = _ObjectStore.set_ins_string_object( bucket, drive_key, drive_uid) from Acquire.Storage import DriveInfo as _DriveInfo drive = _DriveInfo(drive_uid=drive_uid, identifiers=self._identifiers, is_authorised=self._is_authorised, autocreate=True) return drive
def get_drive(self, name, aclrules=None, autocreate=True): """Return the DriveMeta for the Drive that the user has called 'name'. If 'autocreate' is True then this drive is automatically created if it does not exist. Note that the '/' in the name will be interpreted as drive separators. """ if self.is_null(): raise PermissionError( "You cannot get a DriveInfo from a null UserDrives") # break the name into directory parts from Acquire.ObjectStore import string_to_filepath_parts \ as _string_to_filepath_parts parts = _string_to_filepath_parts(name) # first get the root drive... root_name = parts[0] from Acquire.Service import get_service_account_bucket \ as _get_service_account_bucket from Acquire.ObjectStore import ObjectStore as _ObjectStore from Acquire.ObjectStore import string_to_encoded as _string_to_encoded encoded_name = _string_to_encoded(root_name) drive_name = root_name bucket = _get_service_account_bucket() drive_key = "%s/%s/%s" % (_drives_root, self._user_guid, encoded_name) try: drive_uid = _ObjectStore.get_string_object(bucket, drive_key) except: drive_uid = None if drive_uid is not None: from Acquire.Storage import DriveInfo as _DriveInfo drive = _DriveInfo(drive_uid=drive_uid, is_authorised=self._is_authorised, identifiers=self._identifiers) else: drive = None if drive is None: if self._is_authorised and autocreate: # create a new UID for the drive and write this to the # object store from Acquire.ObjectStore import create_uid as _create_uid drive_uid = _create_uid() drive_uid = _ObjectStore.set_ins_string_object( bucket, drive_key, drive_uid) from Acquire.Storage import DriveInfo as _DriveInfo drive = _DriveInfo(drive_uid=drive_uid, identifiers=self._identifiers, is_authorised=self._is_authorised, aclrules=aclrules, autocreate=True) if drive is None: from Acquire.Storage import MissingDriveError raise MissingDriveError("There is no Drive called '%s' available" % name) container = [] # now we have the drive, get the sub-drive in this drive... if len(parts) > 1: for subdrive in parts[1:]: container.append(drive.uid()) drive_name = subdrive drive = self._get_subdrive(drive_uid=drive.uid(), name=drive_name, autocreate=autocreate) if drive is None: from Acquire.Storage import MissingDriveError raise MissingDriveError( "There is no Drive called '%s' available" % name) from Acquire.Storage import DriveMeta as _DriveMeta drivemeta = _DriveMeta(name=drive_name, uid=drive.uid(), container=container, aclrules=drive.aclrules()) drivemeta.resolve_acl(identifiers=self._identifiers) return drivemeta
def _acls_key(self): """Return the key for the ACLs for this accounts group""" from Acquire.ObjectStore import string_to_encoded \ as _string_to_encoded return "accounting/account_group_acls/%s" % \ _string_to_encoded(self._group)