def post(self, res_id): if not resource_manager.is_authenticated(): self.write({ 'success': False, 'error': HYDROSHARE_AUTHENTICATION_ERROR, }) return hs_data = ResourceHydroShareData(resource_manager.hs_api_conn, res_id) data = json.loads(self.request.body.decode('utf-8')) file_and_folder_paths = data.get('files') filesChanged = 'sync' if file_and_folder_paths is None: self.set_status(400) # Bad Request self.write('Could not find "files" in request body.') return for item_path in file_and_folder_paths: # Remove any leading / if item_path.startswith('/'): item_path = item_path[1:] local_data = ResourceLocalData(res_id) # resource_manager.save_file_locally(res_id, item_path) hs_data.download_to_local(local_data, Path(item_path), Path(item_path)) self.write({ 'readMe': local_data.get_readme(), 'rootDir': local_data.get_files_and_folders(), })
def delete(self, res_id): body = json.loads(self.request.body.decode('utf-8')) file_and_folder_paths = body.get('files') if file_and_folder_paths is None: self.set_status(400) # Bad Request self.write('Could not find "files" in request body.') return local_folder = ResourceLocalData(res_id) success_count = 0 failure_count = 0 # Keep track of the folders that have been deleted so we don't try to # delete child files that have already # been deleted deleted_folders = [] results = [] for item_path in file_and_folder_paths: # Remove any leading / if item_path.startswith('/'): item_path = item_path[1:] try: for deleted_folder in deleted_folders: # Check if this file is in a folder that was deleted (a # slash is appended to ensure that a file in, # say, '/My data 2' is not skipped because '/My data' was # deleted) if item_path.startswith(deleted_folder + '/'): # We can skip deleting this file because it was already # deleted with its parent folder break else: # Only runs if the break statement above is never hit # (yes, the indentation is right here) # Try to delete this item deleted_type = local_folder.delete_file_or_folder( item_path) if deleted_type == 'folder': deleted_folders.append(item_path) success_count += 1 results.append({'success': True}) except Exception as e: logging.error(e) results.append({ 'success': False, 'error': { 'type': 'UnknownError', 'message': (f'An unknown error occurred when ' f'attempting to delete {item_path}.') } }) failure_count += 1 self.write({ 'results': results, 'successCount': success_count, 'failureCount': failure_count, })
def get(self, res_id): local_data = ResourceLocalData(res_id) if not local_data.is_downloaded(): resource_manager.save_resource_locally(res_id) self.write({ 'readMe': local_data.get_readme(), 'rootDir': local_data.get_files_and_folders(), })
def get(self, res_id): local_data = ResourceLocalData(res_id) local_data.get_md5(res_id) self.write({ 'success': 'success', 'userInfo': '', })
def get(self, res_id): # Handling authentication first to ensure local data if not present is downloaded from Hydroshare if not resource_manager.is_authenticated(): self.write({ 'success': False, 'error': HYDROSHARE_AUTHENTICATION_ERROR, }) return local_data = ResourceLocalData(res_id) if not local_data.is_downloaded(): resource_manager.save_resource_locally(res_id) self.write({ 'readMe': local_data.get_readme(), 'rootDir': local_data.get_files_and_folders(), })
def put(self, res_id): """ Creates a new file in the local copy of the resource :param res_id: the resource ID :type res_id: str """ body = json.loads(self.request.body.decode('utf-8')) item_type = body.get('type') name = body.get('name') error_msg = None if item_type is None or name is None: error_msg = 'Request must include both "type" and "name" attributes.' if not error_msg and not (item_type == 'file' or item_type == 'folder'): error_msg = '"type" attribute must be either "file" or "folder".' if error_msg: self.set_status(400) # Bad Request self.write({ 'success': False, 'error': { 'type': 'InvalidRequest', 'message': error_msg, }, }) return local_data = ResourceLocalData(res_id) if item_type == 'file': local_data.create_file(name) elif item_type == 'folder': local_data.create_local_folder(name) self.write({ 'success': True, })
def post(self, res_id): """ Uploads a file from the user's computer to the local filesystem :param res_id: the resource ID :type res_id: str """ local_data = ResourceLocalData(res_id) for field_name, files in self.request.files.items(): for info in files: with open(str(local_data.data_path / info['filename']), "wb") as f: f.write(info['body']) self.write({ 'success': True, })
def get(self, res_id): if not resource_manager.is_authenticated(): self.write({ 'success': False, 'error': HYDROSHARE_AUTHENTICATION_ERROR, }) return local_data = ResourceLocalData(res_id) if not local_data.is_downloaded(): self.write({ 'success': False, 'error': WORKSPACE_FILES_ERROR, # 'error' : 'HydroShare files not present in Workspace', }) return else: local_file_data = local_data.get_files_and_folders() # checkFileSyncStatus(temporaryRoot, res_id) checkHydroShareSyncStatus(local_file_data, res_id, True) self.write({ 'readMe': local_data.get_readme(), 'rootDir': local_file_data, })
def checkFileSyncStatus(temporaryRoot, res_id): serverIsLatest = 'HydroShare is latest' localIsLatest = 'Local is Latest' localSyncServer = 'In Sync' isfileExists = '' local_data = ResourceLocalData(res_id) hs_data = ResourceHydroShareData(resource_manager.hs_api_conn, res_id) # find where are the files and its properties in temporaryRoot contents = temporaryRoot['contents'] for file in contents: modified_time_local = file['modifiedTime'] checksum_local = file["checksum"] checksum_hs, modified_time_hs = hs_data.get_modified_time_hs( file['name']) if checksum_hs == None or modified_time_hs == None: syncStatus = " " isfileExists = "File doesn't exist in HydroShare" file.update({ "fileChanged": isfileExists, "syncStatus": syncStatus }) else: if checksum_local != checksum_hs: syncStatus = "Out of Sync" if modified_time_hs < modified_time_local: # add fileChanged value file.update({ "fileChanged": localIsLatest, "syncStatus": syncStatus }) elif modified_time_hs > modified_time_local: file.update({ "fileChanged": serverIsLatest, "syncStatus": syncStatus }) elif checksum_local == checksum_hs: syncStatus = "In Sync" file.update({ "fileChanged": "Local and HydroShare are synced", "syncStatus": syncStatus }) temporaryRoot = sorted(contents, key=lambda x: x['syncStatus'] == ' ')
def checkHydroShareSyncStatus(local_or_hs_file_data, res_id, is_local_data): serverIsLatest = 'HydroShare is latest' localIsLatest = 'Local is Latest' localSyncServer = 'In Sync' isFileExist = '' """ if its localdata then get hydroshare data for the res_id else if hydrosharedata then get local data for the res_id """ if is_local_data: data_to_compare = ResourceHydroShareData(resource_manager.hs_api_conn, res_id) else: data_to_compare = ResourceLocalData(res_id) data_to_check_sync_status = local_or_hs_file_data['contents'] for data in data_to_check_sync_status: addParameters(data, data_to_compare, localIsLatest, serverIsLatest, res_id, is_local_data)
def patch(self, res_id): body = json.loads(self.request.body.decode('utf-8')) local_data = ResourceLocalData(res_id) hs_data = ResourceHydroShareData(resource_manager.hs_api_conn, res_id) file_operations = body['operations'] results = [] success_count = 0 failure_count = 0 for operation in file_operations: method = operation['method'] # 'copy' or 'move' src_uri = operation['source'] dest_uri = operation['destination'] # Split paths into filesystem prefix ('hs' or 'local') and path # relative to the resource root on # that filesystem src_fs, src_path = src_uri.split(':') dest_fs, dest_path = dest_uri.split(':') # If this operation involves HydroShare, make sure we're # authenticated if ((src_path == HS_PREFIX or dest_fs == HS_PREFIX) and not resource_manager.is_authenticated()): results.append({ 'success': False, 'error': HYDROSHARE_AUTHENTICATION_ERROR, }) failure_count += 1 continue # Remove the leading forward slashes src_path = src_path[1:] dest_path = dest_path[1:] # Exactly what operation we perform depends on where the source # and destination files/folders are # Move/copy within HydroShare if src_fs == HS_PREFIX and dest_fs == HS_PREFIX: if method == MOVE: # Move or rename try: hs_data.rename_or_move_file(Path(src_path), Path(dest_path)) results.append({'success': True}) success_count += 1 except FileExistsError: results.append({ 'success': False, 'error': { 'type': 'FileOrFolderExists', 'message': (f'The file {dest_path} already ' 'exists in HydroShare.'), }, }) failure_count += 1 else: # TODO: Copy (https://github.com/hydroshare/hydroshare_jupyter_sync/issues/42) # The frontend never requests this, but if one were to # add such functionality, you'd handle it here raise NotImplementedError('Copy within HydroShare ' 'not implemented') # Move/copy within the local filesystem elif src_fs == LOCAL_PREFIX and dest_fs == LOCAL_PREFIX: if method == MOVE: # Move or rename ResourceLocalData(res_id).rename_or_move_item( src_path, dest_path) results.append({'success': True}) success_count += 1 else: # TODO: Copy (https://github.com/hydroshare/hydroshare_jupyter_sync/issues/42) # The frontend never requests this, but if one were to # add such functionality, you'd handle it here raise NotImplementedError('Copy within the local ' 'filesystem not implemented yet') # Move/copy from the local filesystem to HydroShare elif src_fs == LOCAL_PREFIX and dest_fs == HS_PREFIX: # Transfer the file regardless of if we're moving or copying error = hs_data.upload_from_local(local_data, Path(src_path), Path(dest_path)) if not error and method == MOVE: # Delete the local copy of the file error = (ResourceLocalData(res_id).delete_file_or_folder( src_path)) results.append({ 'success': error is None, 'error': error, }) if error: failure_count += 1 else: success_count += 1 # Move/copy from HydroShare to the local filesystem elif src_fs == HS_PREFIX and dest_fs == LOCAL_PREFIX: # Transfer the file regardless of if we're moving or copying hs_data.download_to_local(local_data, Path(src_path), Path(dest_path)) if method == MOVE: # Delete the HS copy of the file hs_data.delete_file_or_folder(src_path) results.append({'success': True}) success_count += 1 else: msg = f'"source" prefix "{src_fs}" and/or destination ' \ f'prefix "{dest_fs} not recognized. Valid options' \ f' are "hs" and "local"' logging.warning(msg) results.append({ 'success': False, 'error': 'UnrecognizedPathPrefix', 'message': msg, }) failure_count += 1 self.write({ 'results': results, 'successCount': success_count, 'failureCount': failure_count, })
def post(self, res_id): if not resource_manager.is_authenticated(): self.write({ 'success': False, 'error': HYDROSHARE_AUTHENTICATION_ERROR, }) return data = json.loads(self.request.body.decode('utf-8')) file_and_folder_paths = data.get('files') myList = [] if file_and_folder_paths is None: self.set_status(400) # Bad Request self.write('Could not find "files" in request body.') return for item_path in file_and_folder_paths: # file_path = item_path # Remove any leading / if item_path.startswith('/'): file_name = item_path[1:] local_data = ResourceLocalData(res_id) CheckSyncStatusFilesRequestHandler.modified_time_local = local_data.get_md5_files( file_name) # appending local modified time to list hs_data = ResourceHydroShareData(resource_manager.hs_api_conn, res_id) CheckSyncStatusFilesRequestHandler.modified_time_hs = hs_data.get_md5_files( res_id, file_name) if CheckSyncStatusFilesRequestHandler.modified_time_hs < CheckSyncStatusFilesRequestHandler.modified_time_local: CheckSyncStatusFilesRequestHandler.filesChanged = 'local' myDict = { 'resourceId': res_id, 'filesChanged': CheckSyncStatusFilesRequestHandler.filesChanged, 'modified_time_local': CheckSyncStatusFilesRequestHandler.modified_time_local, 'file_name': file_name, 'file_path': item_path } myList.append(myDict) myJson = json.dumps(myList) elif CheckSyncStatusFilesRequestHandler.modified_time_hs > CheckSyncStatusFilesRequestHandler.modified_time_local: myDict = { 'resourceId': res_id, 'filesChanged': CheckSyncStatusFilesRequestHandler.filesChanged, 'modified_time_local': CheckSyncStatusFilesRequestHandler.modified_time_hs, 'file_name': file_name, 'file_path': item_path } myList.append(myDict) myJson = json.dumps(myList) temporaryRoot = local_data.get_files_and_folders() self.write({ 'readMe': local_data.get_readme(), 'rootDir': temporaryRoot, 'myJson': myJson })
def addParameters(data, data_to_compare, localIsLatest, serverIsLatest, res_id, is_local_data): # First iterate through folders, and then recrusively call the same method for each file. if data['type'] == 'folder': for k, v in data.items(): if k == 'contents': for j in v: addParameters(j, data_to_compare, localIsLatest, serverIsLatest, res_id, is_local_data) else: """ TODO: Soumya If checksum present for local file - then local file exist hydroshare file - then file exist in Hydroshare server If checksum matches Then both files are in sync Else If they are not in sync, then check their last update time and identify which is latest. Sync status is dependent upon checksum. So, if checksum is present for both, then the file exist in both HS and local. if local file doesnt have checksum the file is no """ # Identify if its Hydroshare file or local file if data['path'].startswith('hs'): file_name = data['path'][4:] else: file_name = data['path'][7:] # Get checksum for both Hydroshare and local files if is_local_data: item_path = str( ResourceLocalData(res_id).data_path) + '/' + file_name checksum_local = ResourceLocalData(res_id).get_md5_files(item_path) checksum_hs = data_to_compare.checksum_hs( file_name.partition('.')[0], file_name.partition('.')[2]) modified_time_local = str( datetime.datetime.fromtimestamp( Path(item_path).stat().st_mtime)) modified_time_hs = data_to_compare.modified_time_hs( file_name.partition('.')[0], file_name.partition('.')[2]) else: item_path = str(data_to_compare.data_path) + '/' + file_name checksum_local = data_to_compare.get_md5_files(item_path) modified_time_local = None if Path(item_path).exists(): modified_time_local = str( datetime.datetime.fromtimestamp( Path(item_path).stat().st_mtime)) checksum_hs = data['checksum'] modified_time_hs = data['modifiedTime'] syncStatus = " " if checksum_local is None: isFileExist = "File doesn't exist in Local System" data.update({"fileChanged": isFileExist, "syncStatus": syncStatus}) elif checksum_hs is None: isfileExists = "File doesn't exist in HydroShare Server" data.update({ "fileChanged": isfileExists, "syncStatus": syncStatus }) else: if checksum_local != checksum_hs: syncStatus = 'Out of Sync' if modified_time_hs < modified_time_local: # add fileChanged value data.update({ "fileChanged": localIsLatest, "syncStatus": syncStatus }) elif modified_time_hs > modified_time_local: data.update({ "fileChanged": serverIsLatest, "syncStatus": syncStatus }) else: syncStatus = 'In Sync' data.update({ "fileChanged": "Local and HydroShare are synced", "syncStatus": syncStatus })
def get(self, res_id): local_data = ResourceLocalData(res_id) self.write({ 'readMe': local_data.get_readme(), 'rootDir': local_data.get_files_and_folders(), })