Skip to content

Commit a822ace

Browse files
authored
Merge pull request #102 from Virtual-Finland-Development/VFD-339-fix-validations
More data validation fixes/additions
2 parents 3adf0d4 + fa4c49a commit a822ace

4 files changed

Lines changed: 62 additions & 23 deletions

File tree

VirtualFinland.UserAPI/src/VirtualFinland.UsersAPI/Activities/Productizer/Operations/BasicInformation/UpdatePersonBasicInformation.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
using FluentValidation;
12
using MediatR;
23
using Microsoft.EntityFrameworkCore;
34
using Swashbuckle.AspNetCore.Annotations;
45
using VirtualFinland.UserAPI.Data;
6+
using VirtualFinland.UserAPI.Data.Repositories;
57
using VirtualFinland.UserAPI.Exceptions;
68
using VirtualFinland.UserAPI.Helpers;
79
using VirtualFinland.UserAPI.Helpers.Services;
@@ -27,6 +29,23 @@ public Command(string? givenName, string? lastName, string email, string? phoneN
2729
public string Email { get; }
2830
public string? PhoneNumber { get; }
2931
public string? Residency { get; }
32+
33+
public class CommandValidator : AbstractValidator<Command>
34+
{
35+
public CommandValidator(ICountriesRepository countriesRepository)
36+
{
37+
RuleFor(command => command.User.PersonId).NotNull().NotEmpty();
38+
RuleFor(command => command.Email).NotNull().NotEmpty();
39+
40+
var knownCountries = countriesRepository.GetAllCountries().Result;
41+
var knownCountryCodes = knownCountries.Select(x => x.IsoCodeThreeLetter).ToList();
42+
RuleFor(command => command.Residency).Must((residency) =>
43+
{
44+
if (residency is null) return true;
45+
return knownCountryCodes.Contains(residency);
46+
}).WithMessage("Residency is not valid");
47+
}
48+
}
3049
}
3150

3251
public class Handler : IRequestHandler<Command, UpdatePersonBasicInformationResponse>
@@ -45,11 +64,11 @@ public async Task<UpdatePersonBasicInformationResponse> Handle(Command request,
4564
{
4665
var person = await _context.Persons.SingleAsync(p => p.Id == request.User.PersonId, cancellationToken);
4766

48-
person.GivenName = request.GivenName ?? person.GivenName;
49-
person.LastName = request.LastName ?? person.LastName;
67+
person.GivenName = request.GivenName;
68+
person.LastName = request.LastName;
5069
person.Email = request.Email;
51-
person.PhoneNumber = request.PhoneNumber ?? person.PhoneNumber;
52-
person.ResidencyCode = request.Residency ?? person.ResidencyCode;
70+
person.PhoneNumber = request.PhoneNumber;
71+
person.ResidencyCode = request.Residency;
5372

5473
try
5574
{

VirtualFinland.UserAPI/src/VirtualFinland.UsersAPI/Activities/Productizer/Operations/JobApplicantProfile/UpdateJobApplicantProfile.cs

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using VirtualFinland.UserAPI.Exceptions;
99
using VirtualFinland.UserAPI.Helpers;
1010
using VirtualFinland.UserAPI.Helpers.Services;
11-
using VirtualFinland.UserAPI.Helpers.Extensions;
1211
using VirtualFinland.UserAPI.Models.Shared;
1312
using VirtualFinland.UserAPI.Models.UsersDatabase;
1413
using VirtualFinland.UserAPI.Security.Models;
@@ -47,7 +46,7 @@ public Command(
4746

4847
private sealed class WorkPreferencesValidator : AbstractValidator<Request.WorkPreferenceValues>
4948
{
50-
public WorkPreferencesValidator()
49+
public WorkPreferencesValidator(ILanguageRepository languagesRepository)
5150
{
5251
RuleForEach(wp => wp.PreferredMunicipality)
5352
.Must(x => EnumUtilities.TryParseWithMemberName<Municipality>(x, out _));
@@ -63,25 +62,27 @@ public WorkPreferencesValidator()
6362
.Must(x => EnumUtilities.TryParseWithMemberName<WorkingTime>(x!, out _))
6463
.When(x => !string.IsNullOrEmpty(x.WorkingTime));
6564

65+
var knownLanguages = languagesRepository.GetAllLanguages().Result;
66+
var knownLanguageCodes = knownLanguages.Select(x => x.TwoLetterISOLanguageName).ToList();
6667
RuleForEach(wp => wp.WorkingLanguage)
67-
.Must(x => !string.IsNullOrEmpty(x) && x.Length == 2); // TODO: Check if language code is valid ISO 639-1 code
68+
.Must(x =>
69+
{
70+
return !string.IsNullOrEmpty(x) && x.Length == 2 && knownLanguageCodes.Contains(x);
71+
}).WithMessage("WorkingLanguage(s) are not valid");
6872
}
6973
}
7074

7175
public sealed class OccupationsValidator : AbstractValidator<List<Request.Occupation>>
7276
{
73-
private readonly IOccupationsFlatRepository _occupationsFlatRepository;
74-
7577
public OccupationsValidator(IOccupationsFlatRepository occupationsFlatRepository)
7678
{
77-
_occupationsFlatRepository = occupationsFlatRepository;
79+
var knownOccupations = occupationsFlatRepository.GetAllOccupationsFlat().Result;
7880

7981
RuleFor(occupations => occupations)
80-
.MustAsync(async (occupations, cancellationToken) =>
82+
.Must((occupations, cancellationToken) =>
8183
{
8284
if (occupations is null || !occupations.Any()) return true;
8385

84-
var knownOccupations = await _occupationsFlatRepository.GetAllOccupationsFlat();
8586
return occupations.Any(x =>
8687
{
8788
var occupation = knownOccupations.FirstOrDefault(y => y.Notation == x.EscoCode);
@@ -91,12 +92,35 @@ public OccupationsValidator(IOccupationsFlatRepository occupationsFlatRepository
9192
}
9293
}
9394

95+
public sealed class LanguageSkillsValidator : AbstractValidator<List<Request.LanguageSkill>>
96+
{
97+
public LanguageSkillsValidator(ILanguageRepository languagesRepository)
98+
{
99+
var knownLanguages = languagesRepository.GetAllLanguages().Result;
100+
var knownLanguageCodes = knownLanguages.Select(x => x.TwoLetterISOLanguageName).ToList();
101+
102+
RuleFor(languageSkills => languageSkills)
103+
.Must((languageSkills, cancellationToken) =>
104+
{
105+
if (languageSkills is null || !languageSkills.Any()) return true;
106+
107+
return languageSkills.Any(x =>
108+
{
109+
var language = knownLanguages.FirstOrDefault(y => y.TwoLetterISOLanguageName == x.LanguageCode);
110+
return language != null;
111+
});
112+
}).WithMessage("LanguageSkills are not valid");
113+
}
114+
}
115+
94116
public class CommandValidator : AbstractValidator<Command>
95117
{
96-
public CommandValidator()
118+
public CommandValidator(ILanguageRepository languagesRepository, IOccupationsFlatRepository occupationsFlatRepository)
97119
{
98120
RuleFor(command => command.User.PersonId).NotNull().NotEmpty();
99-
RuleFor(command => command.WorkPreferences).SetValidator(new WorkPreferencesValidator());
121+
RuleFor(command => command.WorkPreferences).SetValidator(new WorkPreferencesValidator(languagesRepository));
122+
RuleFor(command => command.Occupations).SetValidator(new OccupationsValidator(occupationsFlatRepository));
123+
RuleFor(command => command.LanguageSkills).SetValidator(new LanguageSkillsValidator(languagesRepository));
100124
}
101125
}
102126
}
@@ -105,21 +129,15 @@ public class Handler : IRequestHandler<Command, Request>
105129
{
106130
private readonly UsersDbContext _context;
107131
private readonly AnalyticsLogger<Handler> _logger;
108-
private readonly IOccupationsFlatRepository _occupationsFlatRepository;
109132

110-
public Handler(UsersDbContext context, AnalyticsLoggerFactory loggerFactory, IOccupationsFlatRepository occupationsFlatRepository)
133+
public Handler(UsersDbContext context, AnalyticsLoggerFactory loggerFactory)
111134
{
112135
_context = context;
113136
_logger = loggerFactory.CreateAnalyticsLogger<Handler>();
114-
_occupationsFlatRepository = occupationsFlatRepository;
115137
}
116138

117139
public async Task<Request> Handle(Command command, CancellationToken cancellationToken)
118140
{
119-
// Validate command async parts
120-
var validator = new Command.OccupationsValidator(_occupationsFlatRepository);
121-
await validator.ValidateAndThrowAsync(command.Occupations, cancellationToken);
122-
123141
var person = await _context.Persons
124142
.Include(p => p.Occupations)
125143
.Include(p => p.Educations)

VirtualFinland.UserAPI/src/VirtualFinland.UsersAPI/Models/Repositories/Language.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,7 @@ public record class Language
77
{
88
[JsonPropertyName("id")]
99
public string? Id { get; set; }
10+
11+
[JsonPropertyName("twoLetterISOLanguageName")]
12+
public string? TwoLetterISOLanguageName { get; set; }
1013
}

VirtualFinland.UsersAPI.UnitTests/Tests/Activities/Productizer/PersonJobApplicantProfile_UnitTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@ public async Task UpdateJobApplicantProfile_WithValidData_ReturnsUpdatedData()
2929
var command = new UpdateJobApplicantProfileCommandBuilder().Build();
3030
command.SetAuth(requestAuthenticatedUser);
3131
var mockLoggerFactory = GetMockedAnalyticsLoggerFactory();
32-
var occupationRepository = new MockOccupationsRepository();
33-
var sut = new UpdateJobApplicantProfile.Handler(_dbContext, mockLoggerFactory, occupationRepository);
32+
var sut = new UpdateJobApplicantProfile.Handler(_dbContext, mockLoggerFactory);
3433

3534
var actual = await sut.Handle(command, CancellationToken.None);
3635

0 commit comments

Comments
 (0)