public with sharing class OneDriveFeature extends CloudStorageBase { private static String externalStorage = 'OneDrive'; public override OperationResult listFiles(Map params) { List> resultFiles = new List>(); OperationResult result; try { Boolean isServiceMode = (Boolean) params.get('isServiceMode'); Boolean myDrive = (Boolean) params.get('myDrive'); Boolean isRootFolder = (Boolean) params.get('isRootFolder'); String folderId = (String) params.get('folderId'); String accessToken = (String) params.get('accessToken'); String level = (String) params.get('level'); System.debug('isServiceMode ' + isServiceMode); System.debug('accessToken ' + accessToken); // endpoint String endpoint = (String.isBlank(folderId) && isRootFolder) ? 'https://graph.microsoft.com/v1.0/me/drive/root/children' : 'https://graph.microsoft.com/v1.0/me/drive/items/' + folderId + '/children'; Map headers = new Map{ 'Authorization' => 'Bearer ' + accessToken }; Http http = new Http(); HttpRequest req = new HttpRequest(); req.setEndpoint(endpoint); req.setMethod('GET'); req.setHeader('Authorization', 'Bearer ' + accessToken); HttpResponse res = http.send(req); if (res.getStatusCode() == 200) { Map resultMap = (Map) JSON.deserializeUntyped(res.getBody()); List files = (List) resultMap.get('value'); for (Object file : files) { Map fileDetails = (Map) file; Map fileData = new Map(); fileData.put('id', (String) fileDetails.get('id')); fileData.put('name', (String) fileDetails.get('name')); fileData.put('createdDateTime', (String) fileDetails.get('createdDateTime')); Map createdBy = (Map) fileDetails.get('createdBy'); if (createdBy != null && createdBy.containsKey('user')) { Map userMap = (Map) createdBy.get('user'); fileData.put('createdBy', (String) userMap.get('displayName')); } else { fileData.put('createdBy', 'Unknown'); } Map parentReference = (Map) fileDetails.get('parentReference'); fileData.put('parents', parentReference != null ? (String) parentReference.get('id') : 'No Parent'); fileData.put('url', fileDetails.containsKey('webUrl') ? (String) fileDetails.get('webUrl') : 'https://onedrive.live.com/?cid=' + fileData.get('id')); if (fileDetails.containsKey('folder')) { fileData.put('mimeType', 'folder'); fileData.put('iconName', 'doctype:folder'); } else { fileData.put('mimeType', 'file'); fileData.put('iconName', 'doctype:unknown'); } resultFiles.add(fileData); } result = OperationResult.success(resultFiles); } else { FME_Logger.error('Failed to list OneDrive files: ' + res.getBody(), 'OneDriveFeature', 'listFiles'); result = OperationResult.error('Error listing files: ' + res.getBody()); } } catch (Exception e) { FME_Logger.error(e.getMessage(), 'OneDriveFeature' + e.getLineNumber(), 'listFiles'); result = OperationResult.error('Error listing files: ' + e.getMessage()); } System.debug('result: ' + result); return result; } public override OperationResult createFolder(Map params){ Map resultMap = new Map(); OperationResult result; try{ String parentFolderId = (String) params.get('parentFolderId'); Boolean isServiceMode = (Boolean) params.get('isServiceMode'); String folderName = (String) params.get('folderName'); String userId = (String) SalesforceEnvironmentUtil.getUserId(); String accessToken = (String) params.get('accessToken'); String endpoint = 'https://graph.microsoft.com/v1.0/me/drive/items/' + parentFolderId + '/children'; Map headers = new Map{ 'Authorization' => 'Bearer ' + accessToken, 'Content-Type' => 'application/json' }; String body = JSON.serialize(new Map{ 'name' => folderName, 'folder' => new Map(), '@microsoft.graph.conflictBehavior' => 'rename' }); HttpResponse res = CloudStorageUtlilty.makeCallout(body, endpoint, headers, 'POST'); System.debug(res.getBody()); if (res.getStatusCode() == 201 || res.getStatusCode() == 200) { String responseBody = res.getBody(); resultMap = (Map) JSON.deserializeUntyped(responseBody); resultMap.put('code', '200'); result = OperationResult.success(resultMap); }else{ System.debug('Failed to create folder: ' + res.getBody()); result = OperationResult.error(res.getBody()); } }catch(Exception e){ System.debug('Exception: '+ e.getMessage()); result = OperationResult.error('Error creating folder: ' + e.getMessage()); } return result; } // to delete file public override OperationResult deleteFile(Map params) { try{ String fileId = (String) params.get('fileId'); String userId = SalesforceEnvironmentUtil.getUserId(); Boolean isServiceMode = (Boolean) params.get('isServiceMode'); String accessToken = (String) params.get('accessToken'); System.debug('>>>fileId=' + fileId + ' >>>userId=' + userId + ' >>>isServiceMode=' + isServiceMode); String endpoint = 'https://graph.microsoft.com/v1.0/me/drive/items/' + fileId; Map headers = new Map(); headers.put('Authorization', 'Bearer ' + accessToken); headers.put('Content-Type', 'application/json'); HttpResponse res = CloudStorageUtlilty.makeCallout(null, endpoint, headers, 'DELETE'); System.debug('Status Code: ' + res.getStatusCode()); System.debug('Response Body: ' + res.getBody()); // Handle response if (res.getStatusCode() == 204) { // String userName = UserInfo.getName(); // String logMsg = userName + ' deleted file with Id "' + fileId + '"'; // FME_Logger.audit('Delete', logMsg, 'GoogleDriveFeature', 'deleteFile'); System.debug('getstatusCode is ====>> is 204'); System.debug('>>>res= when 204 is occur' + res.getBody()); return OperationResult.success(res.getBody()); } else { System.debug('>>>res= when 204 is not occur' + res.getBody()); return OperationResult.error(res.getBody()); } }catch(Exception e){ System.debug('>>>res= when error is catch' + e.getMessage()); return OperationResult.error('Error deleting file: ' + e.getMessage()); } } public override OperationResult renameFile(Map params){ OperationResult result ; System.debug('this is renameFile method'); try{ String fileId = (String) params.get('fileId'); Boolean isServiceMode = (Boolean) params.get('isServiceMode'); String newFileName = (String) params.get('newFileName'); String accessToken = (String) params.get('accessToken'); HttpRequest req = new HttpRequest(); req.setEndpoint('https://graph.microsoft.com/v1.0/me/drive/items/' + fileId); req.setMethod('PATCH'); req.setHeader('Authorization', 'Bearer ' + accessToken); req.setHeader('Content-Type', 'application/json'); req.setBody( JSON.serialize( new Map{ 'name' => newFileName } ) ); Http http = new Http(); HttpResponse res = http.send(req); if (res.getStatusCode() == 200) { System.debug('File renamed successfully'); System.debug('>>>> ' + res.getBody()); System.debug('File renamed successfully.'); result= OperationResult.success(res.getBody()); }else{ System.debug('Failed to rename file: ' + res.getBody()); result= OperationResult.error(res.getBody()); } }catch(Exception e){ result = OperationResult.error('Error rename file: ' + e.getMessage()); } return result; } public override OperationResult moveFileAndFolder(Map params ){ OperationResult result; try{ String fileId = (String) params.get('fileId'); Boolean isServiceMode = (Boolean) params.get('serviceMode'); String newFolderId = (String) params.get('newFolderId'); String oldFolderId = (String) params.get('oldFolderId'); String accessToken = (String) params.get('accessToken'); String userId = (String) SalesforceEnvironmentUtil.getUserId(); System.debug('>>>>fileId=' + fileId); System.debug('>>>>newFolderId=' + newFolderId); System.debug('>>>>oldFolderId=' + oldFolderId); HttpRequest req = new HttpRequest(); req.setMethod('PATCH'); req.setEndpoint('https://graph.microsoft.com/v1.0/me/drive/items/' + fileId); req.setHeader('Authorization', 'Bearer ' + accessToken); req.setHeader('Content-Type', 'application/json'); req.setBody( '{"parentReference":{"id":"' + newFolderId + '"}}' ); Http http = new Http(); HttpResponse res = http.send(req); if (res.getStatusCode() == 200) { System.debug('>>>>' + res.getBody()); System.debug('File moved successfully.'); result = OperationResult.success(res.getBody()); //Add audit log // String userName = UserInfo.getName(); // String logMsg = userName + ' moved file/folder with Id ' + fileId + // ' from oldFolderId ' + oldFolderId + // ' to newFolderId ' + newFolderId; // FME_Logger.audit('Move', logMsg, 'GoogleDriveFeature', 'moveFileAndFolder'); } else { System.debug('Failed to move file: ' + res.getBody()); result = OperationResult.error(res.getBody()); } }catch(Exception e){ result = OperationResult.error('Error moving file: ' + e.getMessage()); } return result; } public override OperationResult linkFiles(String recordId) { List> resultFolders = new List>(); try { List linkedFolders = [ SELECT Id,Name,CreatedDate,CreatedBy.Name,HIC_FilesME__External_Folder_ID__c, HIC_FilesME__Folder_Name__c, HIC_FilesME__Folder_URL__c, HIC_FilesME__Storage_Provider__c, HIC_FilesME__Access_Level__c, HIC_FilesME__Connected_Username__c FROM HIC_FilesME__Linked_Folder__c WHERE HIC_FilesME__Linked_Record__c = :recordId AND HIC_FilesME__Is_Active__c = true ]; for (HIC_FilesME__Linked_Folder__c folder : linkedFolders) { Map folderData = new Map(); folderData.put('id', folder.HIC_FilesME__External_Folder_ID__c); folderData.put('recordId', folder.Id); folderData.put('name', folder.HIC_FilesME__Folder_Name__c); folderData.put('externalStorageType', folder.HIC_FilesME__Storage_Provider__c); folderData.put('accessLevel', folder.HIC_FilesME__Access_Level__c); folderData.put('createdTime', String.valueOf(folder.CreatedDate)); folderData.put('createdBy', folder.CreatedBy != null ? folder.CreatedBy.Name : '-'); folderData.put('linkedBy', folder.HIC_FilesME__Connected_Username__c); folderData.put('url', folder.HIC_FilesME__Folder_URL__c); resultFolders.add(folderData); } System.debug('resultFolders >>>> ' + resultFolders); return OperationResult.success(resultFolders); } catch (Exception e) {FME_Logger.error(e.getMessage(),'LinkedFolderFeature' + e.getLineNumber(),'linkFiles'); return OperationResult.error('Failed to fetch linked folders. ' + e.getMessage()); } } public override OperationResult toLinkFiles(String recordId,String folderDetails,String providerType) { try { System.debug('providerType >>>> ' + providerType); System.debug('recordId >>>> ' + recordId); System.debug('JSON.deserializeUntyped folderDetails >>>> ' + JSON.deserializeUntyped(folderDetails)); Map folderMap = (Map) JSON.deserializeUntyped(folderDetails); HIC_FilesME__Linked_Folder__c linkedFolder = new HIC_FilesME__Linked_Folder__c(); linkedFolder.HIC_FilesME__Linked_Record__c = recordId; linkedFolder.HIC_FilesME__External_Folder_ID__c = (String) folderMap.get('id'); linkedFolder.HIC_FilesME__Folder_Name__c = (String) folderMap.get('name'); //add linkedFolder.HIC_FilesME__Created__c = UserInfo.getUserId(); linkedFolder.HIC_FilesME__Created_Date__c = System.now(); linkedFolder.HIC_FilesME__Connected_Username__c = (String) folderMap.get('linkedBy'); linkedFolder.HIC_FilesME__Folder_URL__c = (String) folderMap.get('url'); linkedFolder.HIC_FilesME__Storage_Provider__c = providerType; // linkedFolder.HIC_FilesME__Access_Level__c = (String) folderMap.get('accessLevel'); linkedFolder.HIC_FilesME__Is_Active__c = true; String key = providerType +' '+ recordId +' '+ (String) folderMap.get('id'); linkedFolder.HIC_FilesME__Key__c = key; upsert linkedFolder HIC_FilesME__Key__c; // insert linkedFolder; System.debug('linkedFolder >>>> ' + linkedFolder); return OperationResult.success(linkedFolder); } catch (Exception e) { FME_Logger.error(e.getMessage(),'LinkedFolderFeature' + e.getLineNumber(),'toLinkFiles' ); return OperationResult.error('Error linking folder: ' + e.getMessage()); } } public override OperationResult unlinkFiles(String recordId, String filesId, Boolean deleteFromDrive) { System.debug('recordId >>>> ' + recordId); System.debug('filesId >>>> ' + filesId); System.debug('deleteFromDrive >>>> ' + deleteFromDrive); OperationResult result; try { List fileLinks = [SELECT Id FROM HIC_FilesME__Linked_Folder__c WHERE HIC_FilesME__Linked_Record__c = :recordId AND HIC_FilesME__External_Folder_ID__c = :filesId]; if (fileLinks.size() > 0) { delete fileLinks; // if (deleteFromDrive) { // deleteFile(filesId, true, null); // } result = OperationResult.success(null); } else { result = OperationResult.error('No record found'); } } catch (Exception e) { result = OperationResult.error('Error unlinking file: ' + e.getMessage()); FME_Logger.error(e.getMessage(), 'GoogleDriveFeature' + e.getLineNumber(), 'unlinkFiles'); } return result; } public override OperationResult downloadFile(Map params) { System.debug('onedrive.downloadFile'); OperationResult result; try { Blob fileBlob = fetchFileAndConvertToBase64(params); System.debug('fileBlob >>>> ' + fileBlob); if (fileBlob != null) { result = OperationResult.success(EncodingUtil.base64Encode(fileBlob)); System.debug('File downloaded successfully.'); } else { result = OperationResult.error('Failed to download file'); } } catch (Exception e) { result = OperationResult.error('Error downloading file: ' + e.getMessage()); FME_Logger.error(e.getMessage(), 'OneDrive' + e.getLineNumber(), 'downloadFile'); } return result; } public static Blob fetchFileAndConvertToBase64(Map params) { Blob fileBlob; try{ Boolean isServiceMode = (Boolean) params.get('isServiceMode'); String fileId = (String) params.get('fileId'); String fileName = (String) params.get('fileName'); String accessToken = (String) params.get('accessToken'); String userId = (String) SalesforceEnvironmentUtil.getUserId(); Map headers = new Map{ 'Authorization' => 'Bearer ' + accessToken }; String downloadUrl = 'https://graph.microsoft.com/v1.0/me/drive/items/' + fileId + '/content'; headers.put('Authorization', 'Bearer ' + accessToken); HttpResponse res = CloudStorageUtlilty.makeCallout(null, downloadUrl, headers, 'GET'); System.debug('res >>>> ' + res); System.debug('Initial status: ' + res.getStatusCode()); // 4. Handle redirect if (res.getStatusCode() == 302) { String redirectUrl = res.getHeader('Location'); System.debug('Redirect URL: ' + redirectUrl); // 5. Second call – NO HEADERS HttpResponse fileRes = CloudStorageUtlilty.makeCallout(null, redirectUrl, new Map(), 'GET'); if (fileRes.getStatusCode() == 200) { fileBlob = fileRes.getBodyAsBlob(); System.debug('File downloaded. Size: ' + fileBlob.size()); } else { System.debug( 'Redirect download failed: ' + fileRes.getStatusCode() + ' body=' + fileRes.getBody() ); } } else { System.debug( 'Unexpected status from Graph: ' + res.getStatusCode() + ' body=' + res.getBody() ); } }Catch(Exception e){ System.debug('Error in fetchFileAndConvertToBase64: ' + e.getMessage()); } return fileBlob; } public override OperationResult emailFile(Map params) { OperationResult result; try { Map mailDetails = (Map) JSON.deserializeUntyped( JSON.serialize(params.get('mailDetails'))); System.debug('mailDetails:- '+ mailDetails); String fileId = (String) params.get('fileId'); String fileName = (String) params.get('fileName'); String mimeType = (String) params.get('toSendFileNameMimeType'); String senderId = (String) mailDetails.get('fromUser'); String toUser = (String) mailDetails.get('toUser'); String ccUser = (String) mailDetails.get('ccUser'); String bccUser = (String) mailDetails.get('bccUser'); String subject = (String) mailDetails.get('subject'); String body = (String) mailDetails.get('body'); System.debug('senderId: '+ senderId ); System.debug('toUser: '+ toUser); System.debug('ccUser: '+ ccUser); System.debug('bccUser:' + bccUser); System.debug('subject: '+ subject); System.debug('body: '+ body); // Build email Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage(); mail.setToAddresses(new List{ toUser }); if (String.isNotBlank(ccUser)) { mail.setCcAddresses(new List{ ccUser }); } if (String.isNotBlank(bccUser)) { mail.setBccAddresses(new List{ bccUser }); } System.debug('senderId: '+ senderId); OrgWideEmailAddress owe = [ SELECT Id, DisplayName, Address FROM OrgWideEmailAddress WHERE Id = :senderId LIMIT 1 ]; if(senderId != 'default'){ System.debug('senderId: '+ owe.id); mail.setOrgWideEmailAddressId(owe.id); } mail.setSubject(subject); mail.setPlainTextBody(body != null ? body.replaceAll('<[^>]+>', '') : ''); // mail.setSenderDisplayName(userId); // Attach file // Blob fileBlob = fetchFileAndConvertToBase64(isServiceMode, userId, fileId); OperationResult op = downloadFile(params); if (op != null && op.data != null) { Blob fileBlob = EncodingUtil.base64Decode((String) op.data); System.debug('fileBlob for email attachment:- '+ fileBlob); Messaging.EmailFileAttachment attachment = new Messaging.EmailFileAttachment(); attachment.setFileName(fileName); attachment.setBody(fileBlob); attachment.setContentType(mimeType); mail.setFileAttachments( new List{ attachment } ); } // Send email Messaging.SendEmailResult[] results = Messaging.sendEmail(new List{ mail }); if (!results.isEmpty() && results[0].isSuccess()) { result = OperationResult.success(null); } else { String errMsg = (!results.isEmpty() && results[0].getErrors().size() > 0) ? results[0].getErrors()[0].getMessage() : 'Unknown send failure'; result = OperationResult.error(errMsg); } } catch (Exception e) { FME_Logger.error(e.getMessage(), 'GoogleDrive' + e.getLineNumber(), 'emailFile'); result = OperationResult.error('Error sending email: ' + e.getMessage()); } return result; } }