using System.IO; using System.Linq; using System.Threading.Tasks; using MalwareMultiScan.Api.Data.Models; using MalwareMultiScan.Api.Services.Interfaces; using MongoDB.Bson; using MongoDB.Driver; using MongoDB.Driver.GridFS; namespace MalwareMultiScan.Api.Services.Implementations { public class ScanResultService : IScanResultService { private const string CollectionName = "ScanResults"; private readonly IGridFSBucket _bucket; private readonly IMongoCollection _collection; private readonly IScanBackendService _scanBackendService; public ScanResultService(IMongoDatabase db, IGridFSBucket bucket, IScanBackendService scanBackendService) { _bucket = bucket; _scanBackendService = scanBackendService; _collection = db.GetCollection(CollectionName); } public async Task CreateScanResult() { var scanResult = new ScanResult { Results = _scanBackendService.List .Where(b => b.Enabled) .ToDictionary(k => k.Id, v => new ScanResultEntry()) }; await _collection.InsertOneAsync(scanResult); return scanResult; } public async Task GetScanResult(string id) { var result = await _collection.FindAsync( Builders.Filter.Where(r => r.Id == id)); return await result.FirstOrDefaultAsync(); } public async Task UpdateScanResultForBackend(string resultId, string backendId, long duration, bool completed = false, bool succeeded = false, string[] threats = null) { await _collection.UpdateOneAsync( Builders.Filter.Where(r => r.Id == resultId), Builders.Update.Set(r => r.Results[backendId], new ScanResultEntry { Completed = completed, Succeeded = succeeded, Duration = duration, Threats = threats ?? new string[] { } })); } public async Task QueueUrlScan(ScanResult result, string fileUrl) { foreach (var backend in _scanBackendService.List.Where(b => b.Enabled)) await _scanBackendService.QueueUrlScan(result, backend, fileUrl); } public async Task StoreFile(string fileName, Stream fileStream) { var objectId = await _bucket.UploadFromStreamAsync( fileName, fileStream); return objectId.ToString(); } public async Task ObtainFile(string id) { if (!ObjectId.TryParse(id, out var objectId)) return null; try { return await _bucket.OpenDownloadStreamAsync(objectId, new GridFSDownloadOptions { Seekable = true }); } catch (GridFSFileNotFoundException) { return null; } } } }