using Microsoft.Extensions.Configuration;
using Microsoft.Graph;
using Microsoft.Identity.Client;
using rgbc_sds.dal.DB;
using rgbc_sds.services.Models;
using System.Net.Http.Headers;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Microsoft.IdentityModel.Tokens;
using static System.Net.WebRequestMethods;
namespace rgbc_sds.services.Services
{
public class SharePointService
{
private readonly IConfiguration _configuration;
private readonly IConfidentialClientApplication _confidentialClientApp;
private readonly rgbc_sdsContext _context;
public SharePointService(IConfiguration configuration, rgbc_sdsContext context)
{
_configuration = configuration;
_confidentialClientApp = ConfidentialClientApplicationBuilder.Create(_configuration["SharePointCredentials:CLIENT_ID"])
.WithClientSecret(_configuration["SharePointCredentials:CLIENT_SECRET"])
.WithAuthority(new Uri($"https://login.microsoftonline.com/{_configuration["SharePointCredentials:TENANT_ID"]}"))
.Build();
_context = context;
}
///
/// Retrieving the access token that is used as authentication.
///
///
public async Task RetrieveAccessTokenAsync()
{
var scopes = new[] { _configuration["SharePointCredentials:SCOPE"] };
var authResult = await _confidentialClientApp.AcquireTokenForClient(scopes).ExecuteAsync();
return authResult.AccessToken;
}
///
/// Configuration of the graph client that is used for all sharepoint actions.
///
///
public async Task ConfigureGraphClient()
{
var accessToken = await RetrieveAccessTokenAsync();
var graphClient = new GraphServiceClient(
new DelegateAuthenticationProvider((requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
return Task.CompletedTask;
}));
return graphClient;
}
///
/// Method that handles the upload of a file to a document type that already has a file uploaded.
/// It checks if there is a file uploaded and deletes the file before uploading the new file.
///
///
///
///
public async Task UploadFilesAsync(sdsShipment s, List files)
{
foreach (var file in files)
{
var fileName = $"{s.indent_number}_{file.File.FileName}";
var folderPath = $"/Shipment Checklist/{s.indent_number}";
using var stream = new MemoryStream();
await file.File.CopyToAsync(stream);
stream.Seek(0, SeekOrigin.Begin);
//Check if file exists
try
{
// check if file has been uploaded for the document type
switch (file.DocumentType)
{
case "ClampingRequest":
if (!string.IsNullOrEmpty(s.clamping_request_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// upload new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "SupplierInvoice":
if (!string.IsNullOrEmpty(s.supplier_invoice_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "BillOfLading":
if (!string.IsNullOrEmpty(s.bill_of_lading_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "ArrivalInvoice":
if (!string.IsNullOrEmpty(s.arrival_invoice_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "ArrivalInvoice2":
if (!string.IsNullOrEmpty(s.arrival_invoice_file2))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "CerificateOfOrigin":
if (!string.IsNullOrEmpty(s.certificate_of_origin_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "PackingList":
if (!string.IsNullOrEmpty(s.packing_list_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "DROToTransport":
if (!string.IsNullOrEmpty(s.dro_to_transport_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "CertificateOfRemoval":
if (!string.IsNullOrEmpty(s.certificate_of_removal_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "ExtendedDetention":
if (!string.IsNullOrEmpty(s.extended_detention_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "VOC":
if (!string.IsNullOrEmpty(s.voc_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "DeptOfHealth":
if (!string.IsNullOrEmpty(s.dept_of_health_inspection_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "SARSDocuments":
if (!string.IsNullOrEmpty(s.sars_documents_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "GRVCompleteRGBC":
if (!string.IsNullOrEmpty(s.grv_complete_RGBC_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "GRVEdwardSnell":
if (!string.IsNullOrEmpty(s.grv_edward_snell_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
case "ACCPACReceipts":
if (!string.IsNullOrEmpty(s.accpac_receipts_file))
{
// delete existing file
await DeleteFileHelper(folderPath, $"{s.indent_number}_{file.OldFileName}");
// deleting the file that was uploaded to replace with new file
await UploadFileHelper(folderPath, fileName, stream);
}
break;
default:
break;
}
}
catch (ServiceException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
//File does not exist, no action needed
}
}
}
///
/// Uploads the file to sharepoint.
///
///
///
///
///
public async Task UploadFileHelper(string folderPath, string fileName, MemoryStream stream)
{
try
{
var graphClient = await ConfigureGraphClient();
//Upload new file
await graphClient.Sites[_configuration["SharePointCredentials:SITE_ID"]]
.Drive
.Root
.ItemWithPath($"{folderPath}/{fileName}")
.Content
.Request()
.PutAsync(stream);
}
catch (Exception ex)
{
throw;
}
}
///
/// Deletes an existing file.
///
///
///
///
public async Task DeleteFileHelper(string folderPath, string fileName)
{
var graphClient = await ConfigureGraphClient();
try
{
var existingFile = await graphClient.Sites[_configuration["SharePointCredentials:SITE_ID"]]
.Drive
.Root
.ItemWithPath($"{folderPath}/{fileName}")
.Request()
.GetAsync();
//If exists, delete the existing file
if (existingFile != null)
{
await graphClient.Sites[_configuration["SharePointCredentials:SITE_ID"]]
.Drive
.Items[existingFile.Id]
.Request()
.DeleteAsync();
}
}
catch (ServiceException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
//File does not exist, no action needed
}
}
///
/// Retrieves the URL for the user to be able to view the uploaded files.
///
///
///
///
public async Task GetSharepointPreviewURL(string folderPath, string fileName)
{
var graphClient = await ConfigureGraphClient();
try
{
ItemPreviewInfo preview = await graphClient.Sites[_configuration["SharePointCredentials:SITE_ID"]]
.Drive
.Root
.ItemWithPath($"{folderPath}/{fileName}")
.Preview()
.Request()
.PostAsync();
return preview.GetUrl;
}
catch (ServiceException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
return "File not Found";
}
}
///
/// Gets all files in a specific folder.
///
///
///
public async Task> GetFilesInFolder(string folderId)
{
var graphClient = await ConfigureGraphClient();
var items = await graphClient.Sites[_configuration["SharePointCredentials:SITE_ID"]].Drive.Items[folderId].Children.Request().GetAsync();
return items.CurrentPage.ToList();
}
///
/// Gets all files within a specific folder path.
///
///
///
///
public async Task GetFolderIdByNameInRoot(string folderName, string folderPath)
{
var graphClient = await ConfigureGraphClient();
// Fetch root items in the document library
var items = await graphClient.Sites[_configuration["SharePointCredentials:SITE_ID"]].Drive.Root.ItemWithPath($"{folderPath}").Children.Request().GetAsync();
var folder = items.CurrentPage.FirstOrDefault(i => i.Name.Equals(folderName, StringComparison.OrdinalIgnoreCase));
return folder?.Id; // Return folder ID or null if not found
}
///
/// Method that handles the moving of files.
///
///
///
///
///
///
public async Task RenameFoldersFiles(string sourceFolderName, string rootFolderName, string newFolderName, IList fileNames)
{
var graphClient = await ConfigureGraphClient();
// get folder to rename
var sourceFolderId = await GetFolderIdByNameInRoot(sourceFolderName, rootFolderName);
// get files within this folder to rename
var sourceFileList = await GetFilesInFolder(sourceFolderId);
// rename the files
var renameFiles = await RenameFiles(sourceFileList, fileNames, newFolderName);
// rename folder with new indent number
var message = await RenameFolder(sourceFolderId, newFolderName);
}
///
/// Rename a folder
///
///
///
///
public async Task RenameFolder(string folderId, string folderName)
{
var graphClient = await ConfigureGraphClient();
var driveItem = new DriveItem
{
Name = folderName,
};
await graphClient.Sites[_configuration["SharePointCredentials:SITE_ID"]].Drive.Items[folderId]
.Request()
.UpdateAsync(driveItem);
return "Folder renamed successfully";
}
///
/// Rename files
///
///
///
///
public async Task RenameFiles(IList files, IList fileNames, string folderName)
{
var graphClient = await ConfigureGraphClient();
foreach (var file in files)
{
foreach (var sharepointFile in fileNames)
{
if (file.Name.Contains(sharepointFile))
{
var updatedFile = new DriveItem
{
Name = folderName + "_" + sharepointFile
};
await graphClient.Sites[_configuration["SharePointCredentials:SITE_ID"]].Drive.Items[file.Id]
.Request()
.UpdateAsync(updatedFile);
}
}
}
return "Folder renamed successfully";
}
}
}