using Microsoft.AspNetCore.Mvc; using ServiceInside.Filter; using ServiceInside.Service; using ServiceShared; using ServiceShared.Crypto; using ServiceShared.Models.Request; using ServiceShared.Models.Response; using ServiceShared.Models.Response.Exception; namespace ServiceInside.Controllers { [ApiController] [ServiceOutsideRequest] [Route("[controller]")] public class ServiceOutsideController : BaseController { /// /// Constructor of ServiceOutsideController, that getting instance of configuration and KeyPair and request from the outside service /// /// Configuration from appsettings.json /// Server Curve25519 KeyPair public ServiceOutsideController(IConfiguration configuration, KeyPair keyPair) : base(configuration, keyPair) { } /// /// Incoming subscribe request from the ServiceOutside /// /// Json Response [Route("subscribe")] [HttpPost] public JsonResult Subscribe(EncryptedRequest encrypted) { EncryptedResponse response = null; try { this.Debug(encrypted, "REQUEST"); if (encrypted.ValidSignature(this.GetClientSharedKey(), this.GetClientSignature(), this.GetClientSignatureKey())) { Subscribe subscribe = encrypted.Decrypt(this.GetClientSharedKey()); if(subscribe != null) { ResponseException validationException = ServiceShared.Models.Request.Subscribe.Validate(subscribe); if (validationException != null) { response = new EncryptedResponse("ResponseException", validationException, this.GetClientSharedKey()); } else if (string.IsNullOrEmpty(subscribe.pgs_hash)) { response = new EncryptedResponse("ResponseException", new MissingArgumentException("pgs_hash"), this.GetClientSharedKey()); } else { BackgroundWorker.Subscribe(subscribe.pgs, subscribe.udid); response = new EncryptedResponse("Success", null, this.GetClientSharedKey()); } } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } catch (Exception ex) { Log.Critical(ex, "ServiceInside.Controllers.ServiceInsideController", "Subscribe"); } this.Debug(encrypted, "RESPONSE"); return new JsonResult(response); } /// /// Incoming unsubscribe request from the ServiceOutside /// /// Json Response [Route("unsubscribe")] [HttpPost] public JsonResult Unsubscribe(EncryptedRequest encrypted) { EncryptedResponse response = null; try { this.Debug(encrypted, "REQUEST"); if (encrypted.ValidSignature(this.GetClientSharedKey(), this.GetClientSignature(), this.GetClientSignatureKey())) { Subscribe subscribe = encrypted.Decrypt(this.GetClientSharedKey()); if (subscribe != null) { ResponseException validationException = ServiceShared.Models.Request.Subscribe.Validate(subscribe); if (validationException != null) { response = new EncryptedResponse("ResponseException", validationException, this.GetClientSharedKey()); } else { BackgroundWorker.Unsubscribe(subscribe.pgs, subscribe.pgs_hash, subscribe.udid); response = new EncryptedResponse("Success", null, this.GetClientSharedKey()); } } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } catch (Exception ex) { Log.Critical(ex, "ServiceInside.Controllers.ServiceInsideController", "Unsubscribe"); } this.Debug(encrypted, "RESPONSE"); return new JsonResult(response); } /// /// Incoming delete device request from the ServiceOutside /// /// Json Response [Route("delete_device")] [HttpPost] public JsonResult DeleteDevice(EncryptedRequest encrypted) { EncryptedResponse response = null; try { this.Debug(encrypted, "REQUEST"); if (encrypted.ValidSignature(this.GetClientSharedKey(), this.GetClientSignature(), this.GetClientSignatureKey())) { DeleteDevice deleteDevice = encrypted.Decrypt(this.GetClientSharedKey()); if (deleteDevice != null) { if (string.IsNullOrEmpty(deleteDevice.udid)) { response = new EncryptedResponse("ResponseException", new MissingArgumentException("udid"), this.GetClientSharedKey()); } else if (deleteDevice.udid.Length < 10 || deleteDevice.udid.Length > 64) { response = new EncryptedResponse("ResponseException", new InvalidArgumentException("udid", "wrong length"), this.GetClientSharedKey()); } if (string.IsNullOrEmpty(deleteDevice.verificator_hash)) { response = new EncryptedResponse("ResponseException", new MissingArgumentException("verificator_hash"), this.GetClientSharedKey()); } else if (deleteDevice.verificator_hash.Length != 128) { response = new EncryptedResponse("ResponseException", new InvalidArgumentException("verificator_hash", "wrong length"), this.GetClientSharedKey()); } else { if(BackgroundWorker.DeleteDevice(deleteDevice.udid, deleteDevice.verificator_hash)) { response = new EncryptedResponse("success", null, this.GetClientSharedKey()); } else { Log.Critical(new Exception("Could not delete results for udid in the database, UDID=" + deleteDevice.udid + ", VerificationHash=" + deleteDevice.verificator_hash), "ServiceOutside.Controllers.ResultsController", "DeleteDevice(EncryptedRequest)"); response = new EncryptedResponse("ResponseException", new UnknownException(), this.GetClientSharedKey()); } } } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } catch (Exception ex) { Log.Critical(ex, "ServiceInside.Controllers.ServiceInsideController", "Subscribe"); } this.Debug(encrypted, "RESPONSE"); return new JsonResult(response); } /// /// returns encrypted results /// /// Json Response [Route("get_download")] [HttpPost] public JsonResult GetDownload(EncryptedRequest encrypted) { EncryptedResponse response = null; try { this.Debug(encrypted, "REQUEST"); if (encrypted.ValidSignature(this.GetClientSharedKey(), this.GetClientSignature(), this.GetClientSignatureKey())) { CheckResults check = encrypted.Decrypt(this.GetClientSharedKey()); if (check != null && !string.IsNullOrEmpty(check.pgs) && !string.IsNullOrEmpty(check.udid)) { Download download = BackgroundWorker.GetDownload(check.pgs, check.udid); response = new EncryptedResponse("Download", download, this.GetClientSharedKey()); } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } catch (Exception ex) { Log.Critical(ex, "ServiceInside.Controllers.ServiceInsideController", "Get"); } this.Debug(encrypted, "RESPONSE"); return new JsonResult(response); } /// /// Incoming notification from the ServiceOutside about, that the results was pickedup successfully by patient /// /// Json Response [Route("pickedup")] [HttpPost] public JsonResult PickedUp(EncryptedRequest encrypted) { EncryptedResponse response = null; try { this.Debug(encrypted, "REQUEST"); if (encrypted.ValidSignature(this.GetClientSharedKey(), this.GetClientSignature(), this.GetClientSignatureKey())) { CheckFileChecksum check = encrypted.Decrypt(this.GetClientSharedKey()); if (check != null && !string.IsNullOrEmpty(check.pgs) && !string.IsNullOrEmpty(check.udid) && !string.IsNullOrEmpty(check.file_checksum)) { BackgroundWorker.SetPickedUpResultsAsync(check.pgs, check.udid, check.file_checksum); response = new EncryptedResponse("Success", new Success("check status for " + check.pgs + "(PGS), " + check.udid + "(UDID)"), this.GetClientSharedKey()); } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } else { response = new EncryptedResponse("ResponseException", new InvalidClientException(), this.GetClientSharedKey()); } } catch (Exception ex) { Log.Critical(ex, "ServiceInside.Controllers.ServiceInsideController", "PickedUp(EncryptedRequest)"); } this.Debug(encrypted, "RESPONSE"); return new JsonResult(response); } } }