protected override async Task Handle(CreatePresenceCheckCommand request, CancellationToken cancellationToken) { var now = DateTime.UtcNow; var profiles = await repository.GetProfilesByCovidPassAsync(request.CovidPass, cancellationToken); if (!profiles.Any()) { throw new DomainException($"No profiles found with {nameof(request.CovidPass)}: '{request.CovidPass}'"); } foreach (var profile in profiles) { // meeting notes - always create presente check //var activeCheck = await context.PresenceChecks.AsNoTracking() // .Where(x => x.ProfileId == profile.Id && now < x.DeadLineCheck // && x.Status != PresenceCheckStatus.OK) // .ToListAsync(cancellationToken); if (profile.ActiveQuarantine(now)) { var check = new PresenceCheck(profile.Id, now, now.Add(request.DeadLineTime), request.Status); profile.AddPresenceCheck(check); } } await context.SaveChangesAsync(cancellationToken); }
protected override async Task Handle(VerifyProfileCommand request, CancellationToken cancellationToken) { var profile = await repository.GetProfileAsync(request.ProfileId, request.DeviceId, cancellationToken); if (profile == null) { throw new DomainException("Profile not found"); } var now = DateTime.UtcNow; var nonce = await context.PushNonces.SingleOrDefaultAsync(x => x.Id == profile.PushToken && x.ExpiredOn > DateTime.UtcNow, cancellationToken); if (nonce?.Body != request.Nonce) { throw new DomainException("Nonce not found or expired"); } if (profile.ClientInfo.OperationSystem == Platform.Android) { var attestation = androidAttestation.ParseAndVerify(request.SignedAttestationStatement); if (attestation == null) { throw new DomainException("Device isn't attested"); } } profile.AssignCovidPass(request.CovidPass); profile.AssignPublicKey(request.PublicKey); profile.Verify(); await context.SaveChangesAsync(cancellationToken); }
public async Task <PushNonce> Handle(GeneratePushNonceCommand request, CancellationToken cancellationToken) { var profile = await repository.GetProfileAsync(request.ProfileId, request.DeviceId, cancellationToken); if (profile == null) { throw new DomainException("Profile not found"); } if (string.IsNullOrEmpty(profile.PushToken)) { throw new DomainException("Push token is required please update profile"); } var instanceInfo = await instanceIdService.GetInstanceInfoAsync(profile.PushToken, cancellationToken); if (instanceInfo == null) { throw new DomainException("Push token is invalid"); } if (instanceInfo.Platform != profile.ClientInfo.OperationSystem || instanceInfo.Application != profile.ClientInfo.Integrator) { throw new DomainException("Push token is invalid or from wrong platform"); } var pushNonce = await context.PushNonces.SingleOrDefaultAsync(x => x.Id == profile.PushToken, cancellationToken); if (pushNonce != null) { pushNonce.Update(nonceGenerator.Generate(), DateTime.UtcNow, DateTime.UtcNow.Add(request.TokenExpiration)); } else { pushNonce = new PushNonce(profile.PushToken, nonceGenerator.Generate(), DateTime.UtcNow, DateTime.UtcNow.Add(request.TokenExpiration)); await context.PushNonces.AddAsync(pushNonce, cancellationToken); } await context.SaveChangesAsync(cancellationToken); var message = new Notification { Data = new Dictionary <string, object> { { "type", "PUSH_NONCE" }, { "Nonce", pushNonce.Body } }, Priority = "high", ContentAvailable = true }; var sendNonceCommand = new SendPushNotificationCommand(profile.Id, message); await mediator.Send(sendNonceCommand, cancellationToken); return(pushNonce); }
protected override async Task Handle(DeleteLocationsFromContactsCommand request, CancellationToken cancellationToken) { var contactsWithLocations = await context.Contacts .Where(x => x.Latitude != null || x.Longitude != null) .ToListAsync(cancellationToken); foreach (var contact in contactsWithLocations) { contact.ClearLocation(); } await context.SaveChangesAsync(cancellationToken); }
public static async Task SaveVirusInfoAsync(string virusInfo) { CoronaContext context = new CoronaContext(); context.Database.EnsureCreated(); CoronaVirusSummary coronaVirusSummary = await context.CoronaVirusSummaries.SingleOrDefaultAsync(x => x.Date == DateTime.Today, new CancellationToken()); if (coronaVirusSummary == null) { context.CoronaVirusSummaries.Add(new CoronaVirusSummary() { Date = DateTime.Today, VirusInfo = virusInfo }); int num = await context.SaveChangesAsync(new CancellationToken()); } else { coronaVirusSummary.VirusInfo = virusInfo; int num = await context.SaveChangesAsync(new CancellationToken()); } }
protected override async Task Handle(ConvertContactsTimestampCommand request, CancellationToken cancellationToken) { var contacts = await context.Contacts.ToListAsync(cancellationToken); foreach (var contact in contacts) { if (contact.Timestamp.HasValue) { var creationDate = convertService.UnixTimeStampToDateTime(contact.Timestamp.Value).Date; contact.SetCreationDate(creationDate); } } await context.SaveChangesAsync(cancellationToken); }
protected override async Task Handle(DeleteOldProfilesCommand request, CancellationToken cancellationToken) { var treshold = DateTime.UtcNow.Add(-request.Interval); var expiredProfiles = await context.Profiles .Where(x => x.CreatedOn.HasValue && x.CreatedOn.Value <= treshold) .ToListAsync(cancellationToken); if (expiredProfiles.Any()) { var builder = new StringBuilder(); expiredProfiles.ForEach(x => builder.Append($"{x.CovidPass};")); log.LogInformation($"deleting profiles with covid passes {builder}"); context.Profiles.RemoveRange(expiredProfiles); await context.SaveChangesAsync(cancellationToken); } }
protected override async Task Handle(UpdatePresenceCheckCommand request, CancellationToken cancellationToken) { var profile = await repository.GetProfileAsync(request.ProfileId, request.DeviceId, request.CovidPass, cancellationToken); if (profile == null) { throw new DomainException("Profile not found"); } var nonceQuery = new RetrieveNonceQuery(profile.CovidPass); var nonceCache = await mediator.Send(nonceQuery, cancellationToken); if (nonceCache == null) { throw new DomainException("Invalid nonce"); } if (nonceCache.Nonce != request.Nonce) { throw new DomainException("Invalid nonce"); } var now = DateTime.UtcNow; var pendingSuspectedPresenceCheck = await context.PresenceChecks .Where(x => x.ProfileId == profile.Id) .Where(x => x.Status == PresenceCheckStatus.SUSPECTED) .Where(x => x.CreatedOn <= now && now <= x.DeadLineCheck) .FirstOrDefaultAsync(cancellationToken); if (pendingSuspectedPresenceCheck == null) { throw new DomainException("There is no active check for given covid pass"); } var newStatus = request.Status switch { Contracts.Requests.PresenceCheckStatus.OK => PresenceCheckStatus.OK, Contracts.Requests.PresenceCheckStatus.LEFT => PresenceCheckStatus.LEFT, _ => PresenceCheckStatus.SUSPECTED }; pendingSuspectedPresenceCheck.UpdateStatus(newStatus); await context.SaveChangesAsync(cancellationToken); } }
protected override async Task Handle(VerifyProfileCommand request, CancellationToken cancellationToken) { var profile = await repository.GetProfileAsync(request.ProfileId, request.DeviceId, cancellationToken); if (profile == null) { throw new DomainException("Profile not found"); } var now = DateTime.UtcNow; var nonce = await context.PushNonces.SingleOrDefaultAsync(x => x.Id == profile.PushToken && x.ExpiredOn > DateTime.UtcNow, cancellationToken); if (nonce?.Body != request.Nonce) { throw new DomainException("Nonce not found or expired"); } if (profile.ClientInfo.OperationSystem == Platform.Android) { var attestation = androidAttestation.ParseAndVerify(request.SignedAttestationStatement); if (attestation == null || !attestation.BasicIntegrity || !attestation.CtsProfileMatch) { throw new DomainException("Device isn't attested"); } var certDigest = new byte[] { 0x80, 0xc0, 0xdc, 0x5c, 0x6f, 0x43, 0xd4, 0x97, 0xc4, 0x5a, 0xed, 0x7e, 0x36, 0x98, 0x8a, 0xbe, 0x48, 0xd5, 0xfd, 0xcc, 0xbb, 0xfa, 0xbb, 0xbf, 0x87, 0x86, 0x93, 0x1e, 0x59, 0xdd, 0x1d, 0xaf }; if (attestation.ApkPackageName != "sk.nczi.ekarantena" || !certDigest.SequenceEqual(attestation.ApkCertificateDigestSha256)) { throw new DomainException("Device is not using the legitimate app"); } } profile.AssignCovidPass(request.CovidPass); profile.AssignPublicKey(request.PublicKey); profile.Verify(); await context.SaveChangesAsync(cancellationToken); }
protected override async Task Handle(DeleteExposureKeysCommand request, CancellationToken cancellationToken) { context.ExposureKeys.RemoveRange(request.ExposureKeys); await context.SaveChangesAsync(cancellationToken); }