using System.IO; using System.Linq; using System.Threading.Tasks; using MalwareMultiScan.Api.Data.Models; using MongoDB.Bson; using MongoDB.Driver; using MongoDB.Driver.GridFS; namespace MalwareMultiScan.Api.Services { /// /// Scan results service. /// public class ScanResultService { private const string CollectionName = "ScanResults"; private readonly GridFSBucket _bucket; private readonly IMongoCollection _collection; private readonly ScanBackendService _scanBackendService; /// /// Create scan result service. /// /// Mongo database. /// Scan backend service. public ScanResultService(IMongoDatabase db, ScanBackendService scanBackendService) { _scanBackendService = scanBackendService; _bucket = new GridFSBucket(db); _collection = db.GetCollection(CollectionName); } /// /// Create scan result. /// /// Scan result. 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; } /// /// Get scan result. /// /// Scan result id. /// Scan result. public async Task GetScanResult(string id) { var result = await _collection.FindAsync( Builders.Filter.Where(r => r.Id == id)); return await result.FirstOrDefaultAsync(); } /// /// Update scan status for the backend. /// /// Result id. /// Backend id. /// If the scan has been completed. /// If the scan has been succeeded. /// List of found threats. public async Task UpdateScanResultForBackend(string resultId, string backendId, 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, Threats = threats ?? new string[] { } })); } /// /// Queue URL scan. /// /// Scan result instance. /// File URL. public async Task QueueUrlScan(ScanResult result, string fileUrl) { foreach (var backend in _scanBackendService.List.Where(b => b.Enabled)) await _scanBackendService.QueueUrlScan(result, backend, fileUrl); } /// /// Store file. /// /// File name. /// File stream. /// Stored file id. public async Task StoreFile(string fileName, Stream fileStream) { var objectId = await _bucket.UploadFromStreamAsync( fileName, fileStream); return objectId.ToString(); } /// /// Obtain stored file stream. /// /// File id. /// File seekable stream. public async Task ObtainFile(string id) { if (!ObjectId.TryParse(id, out var objectId)) return null; return await _bucket.OpenDownloadStreamAsync(objectId, new GridFSDownloadOptions { Seekable = true }); } } }