Add UK education verification and security fixes
Features: - Add UK institution recognition (170+ universities) - Add diploma mill detection (100+ blacklisted institutions) - Add education verification service with date plausibility checks - Add local file storage option (no Azure required) - Add default admin user seeding on startup - Enhance Serilog logging with file output Security fixes: - Fix path traversal vulnerability in LocalFileStorageService - Fix open redirect in login endpoint (use LocalRedirect) - Fix password validation message (12 chars, not 6) - Fix login to use HTTP POST endpoint (avoid Blazor cookie issues) Code improvements: - Add CancellationToken propagation to CV parser - Add shared helpers (JsonDefaults, DateHelpers, ScoreThresholds) - Add IUserContextService for user ID extraction - Parallelized company verification in ProcessCVCheckJob - Add 28 unit tests for education verification Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ public sealed class ProcessCVCheckJobTests : IDisposable
|
||||
private readonly Mock<IFileStorageService> _fileStorageServiceMock;
|
||||
private readonly Mock<ICVParserService> _cvParserServiceMock;
|
||||
private readonly Mock<ICompanyVerifierService> _companyVerifierServiceMock;
|
||||
private readonly Mock<IEducationVerifierService> _educationVerifierServiceMock;
|
||||
private readonly Mock<ITimelineAnalyserService> _timelineAnalyserServiceMock;
|
||||
private readonly Mock<ILogger<ProcessCVCheckJob>> _loggerMock;
|
||||
private readonly ProcessCVCheckJob _sut;
|
||||
@@ -37,6 +38,7 @@ public sealed class ProcessCVCheckJobTests : IDisposable
|
||||
_fileStorageServiceMock = new Mock<IFileStorageService>();
|
||||
_cvParserServiceMock = new Mock<ICVParserService>();
|
||||
_companyVerifierServiceMock = new Mock<ICompanyVerifierService>();
|
||||
_educationVerifierServiceMock = new Mock<IEducationVerifierService>();
|
||||
_timelineAnalyserServiceMock = new Mock<ITimelineAnalyserService>();
|
||||
_loggerMock = new Mock<ILogger<ProcessCVCheckJob>>();
|
||||
|
||||
@@ -45,6 +47,7 @@ public sealed class ProcessCVCheckJobTests : IDisposable
|
||||
_fileStorageServiceMock.Object,
|
||||
_cvParserServiceMock.Object,
|
||||
_companyVerifierServiceMock.Object,
|
||||
_educationVerifierServiceMock.Object,
|
||||
_timelineAnalyserServiceMock.Object,
|
||||
_loggerMock.Object);
|
||||
}
|
||||
@@ -159,7 +162,7 @@ public sealed class ProcessCVCheckJobTests : IDisposable
|
||||
|
||||
// Assert
|
||||
_cvParserServiceMock.Verify(
|
||||
x => x.ParseAsync(It.IsAny<Stream>(), "resume.pdf"),
|
||||
x => x.ParseAsync(It.IsAny<Stream>(), "resume.pdf", It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
|
||||
_dbContext.ChangeTracker.Clear();
|
||||
@@ -843,7 +846,7 @@ public sealed class ProcessCVCheckJobTests : IDisposable
|
||||
x => x.DownloadAsync(It.IsAny<string>()),
|
||||
Times.Never);
|
||||
_cvParserServiceMock.Verify(
|
||||
x => x.ParseAsync(It.IsAny<Stream>(), It.IsAny<string>()),
|
||||
x => x.ParseAsync(It.IsAny<Stream>(), It.IsAny<string>(), It.IsAny<CancellationToken>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
@@ -1007,6 +1010,7 @@ public sealed class ProcessCVCheckJobTests : IDisposable
|
||||
private void SetupDefaultMocks(
|
||||
CVData? cvData = null,
|
||||
List<CompanyVerificationResult>? verificationResults = null,
|
||||
List<EducationVerificationResult>? educationResults = null,
|
||||
TimelineAnalysisResult? timelineResult = null)
|
||||
{
|
||||
cvData ??= CreateTestCVData();
|
||||
@@ -1017,7 +1021,7 @@ public sealed class ProcessCVCheckJobTests : IDisposable
|
||||
.ReturnsAsync(new MemoryStream());
|
||||
|
||||
_cvParserServiceMock
|
||||
.Setup(x => x.ParseAsync(It.IsAny<Stream>(), It.IsAny<string>()))
|
||||
.Setup(x => x.ParseAsync(It.IsAny<Stream>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(cvData);
|
||||
|
||||
if (verificationResults != null)
|
||||
@@ -1040,6 +1044,12 @@ public sealed class ProcessCVCheckJobTests : IDisposable
|
||||
.ReturnsAsync(CreateDefaultVerificationResult());
|
||||
}
|
||||
|
||||
_educationVerifierServiceMock
|
||||
.Setup(x => x.VerifyAll(
|
||||
It.IsAny<List<EducationEntry>>(),
|
||||
It.IsAny<List<EmploymentEntry>?>()))
|
||||
.Returns(educationResults ?? []);
|
||||
|
||||
_timelineAnalyserServiceMock
|
||||
.Setup(x => x.Analyse(It.IsAny<List<EmploymentEntry>>()))
|
||||
.Returns(timelineResult);
|
||||
|
||||
Reference in New Issue
Block a user