Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,40 @@ public void ActivateDelegateUser_activates_delegate_user()
userDataService.GetDelegateUserById(delegateUserId)!.Active.Should().BeTrue();
}

[Test]
public void SetDelegateUserLearningHubAuthId_correctly_sets_delegates_learningHubAuthId()
{
using var transaction = new TransactionScope();

// Given
const int delegateId = 3;
const int learningHubAuthId = 1234;

// When
userDataService.SetDelegateUserLearningHubAuthId(delegateId, learningHubAuthId);

// Then
var result = userDataService.GetDelegateUserLearningHubAuthId(delegateId);

result.Should().NotBeNull()
.And.Subject.Should().Be(learningHubAuthId);
}

[Test]
public void GetDelegateUserLearningHubAuthId_returns_null_delegate_learningHubAuthId()
{
using var transaction = new TransactionScope();

// Given
const int delegateId = 3;

// When
var result = userDataService.GetDelegateUserLearningHubAuthId(delegateId);

// Then
result.Should().BeNull();
}

[Test]
public void UpdateDelegateLhLoginWarningDismissalStatus_changes_delegate_dismissal_status()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
namespace DigitalLearningSolutions.Data.Tests.Services
{
using System;
using DigitalLearningSolutions.Data.DataServices.UserDataService;
using DigitalLearningSolutions.Data.Exceptions;
using DigitalLearningSolutions.Data.Models.Signposting;
using DigitalLearningSolutions.Data.Services;
using FakeItEasy;
using FluentAssertions;
using NUnit.Framework;

public class LearningHubLinkServiceTests
{
private ILearningHubLinkService learningHubLinkService = null!;
private ILearningHubSsoSecurityService learningHubSsoSecurityService = null!;
private IUserDataService userDataService = null!;

[SetUp]
public void Setup()
{
userDataService = A.Fake<IUserDataService>();
learningHubSsoSecurityService = A.Fake<ILearningHubSsoSecurityService>();
A.CallTo(() => learningHubSsoSecurityService.VerifyHash("56789", "invalid-hash")).Returns(false);
A.CallTo(() => learningHubSsoSecurityService.VerifyHash("12345", "valid-hash")).Returns(true);
learningHubLinkService = new LearningHubLinkService(learningHubSsoSecurityService, userDataService);
}

[Test]
public void
ValidateLinkingRequestAndExtractDestinationResourceId_throws_exception_when_stored_sessionIdentifier_is_invalid()
{
// Given
var linkLearningHubRequest = new LinkLearningHubRequest
{
Hash = "valid-hash",
State = $"{Guid.NewGuid()}_refId:1234",
UserId = 12345,
};

// When
Action act = () =>
learningHubLinkService.ValidateLinkingRequestAndExtractDestinationResourceId(
linkLearningHubRequest,
"invalid-guid"
);

// Then
act.Should().Throw<LearningHubLinkingRequestException>()
.WithMessage("Invalid Learning Hub linking request session identifier.");
}

[Test]
public void
ValidateLinkingRequestAndExtractDestinationResourceId_throws_exception_when_verifyHash_returns_false()
{
// Given
var storedSessionIdentifier = Guid.NewGuid();
var linkLearningHubRequest = new LinkLearningHubRequest
{
Hash = "invalid-hash",
State = $"{storedSessionIdentifier}_refId:56789",
UserId = 56789,
};

// When
Action act = () => learningHubLinkService.ValidateLinkingRequestAndExtractDestinationResourceId(
linkLearningHubRequest,
storedSessionIdentifier.ToString()
);

// Then
act.Should().Throw<LearningHubLinkingRequestException>().WithMessage("Invalid Learning Hub UserId hash.");
}

[Test]
public void
ValidateLinkingRequestAndExtractDestinationResourceId_throws_exception_when_sessionIdentifier_does_not_match()
{
// Given
var storedSessionIdentifier = Guid.NewGuid();
var linkLearningHubRequest = new LinkLearningHubRequest
{
Hash = "valid-hash",
State = $"{Guid.NewGuid()}_refId:1234",
UserId = 12345,
};

// When
Action act = () => learningHubLinkService.ValidateLinkingRequestAndExtractDestinationResourceId(
linkLearningHubRequest,
storedSessionIdentifier.ToString()
);

// Then
act.Should().Throw<LearningHubLinkingRequestException>()
.WithMessage("Invalid Learning Hub linking session.");
}

[Test]
public void ValidateLinkingRequestAndExtractDestinationResourceId_throws_exception_when_state_is_incomplete()
{
// Given
var storedSessionIdentifier = Guid.NewGuid();
var linkLearningHubRequest = new LinkLearningHubRequest
{
Hash = "valid-hash",
State = $"{storedSessionIdentifier}",
UserId = 12345,
};

// When
Action act = () => learningHubLinkService.ValidateLinkingRequestAndExtractDestinationResourceId(
linkLearningHubRequest,
storedSessionIdentifier.ToString()
);

// Then
act.Should().Throw<LearningHubLinkingRequestException>().WithMessage("Invalid Learning Hub linking state.");
}

[Test]
public void
ValidateLinkingRequestAndExtractDestinationResourceId_throws_exception_when_state_sessionIdentifier_is_not_guid()
{
// Given
var storedSessionIdentifier = Guid.NewGuid();
var linkLearningHubRequest = new LinkLearningHubRequest
{
Hash = "valid-hash",
State = "not-a-guid_refId:1234",
UserId = 12345,
};

// When
Action act = () => learningHubLinkService.ValidateLinkingRequestAndExtractDestinationResourceId(
linkLearningHubRequest,
storedSessionIdentifier.ToString()
);

// Then
act.Should().Throw<LearningHubLinkingRequestException>()
.WithMessage("Invalid Learning Hub linking session.");
}

[Test]
public void
ValidateLinkingRequestAndExtractDestinationResourceId_returns_null_when_resource_id_could_not_be_parsed()
{
// Given
var storedSessionIdentifier = Guid.NewGuid();
var linkLearningHubRequest = new LinkLearningHubRequest
{
Hash = "valid-hash",
State = $"{storedSessionIdentifier}_refId:badInteger",
UserId = 12345,
};

// When
var result = learningHubLinkService.ValidateLinkingRequestAndExtractDestinationResourceId(
linkLearningHubRequest,
storedSessionIdentifier.ToString()
);

// Then
result.Should().BeNull();
}

[Test]
public void
ValidateLinkingRequestAndExtractDestinationResourceId_returns_resourceId_when_request_parsed_successfully()
{
// Given
var storedSessionIdentifier = Guid.NewGuid();
var linkLearningHubRequest = new LinkLearningHubRequest
{
Hash = "valid-hash",
State = $"{storedSessionIdentifier}_refId:1234",
UserId = 12345,
};

// When
var result = learningHubLinkService.ValidateLinkingRequestAndExtractDestinationResourceId(
linkLearningHubRequest,
storedSessionIdentifier.ToString()
);

// Then
result.Should().Be(1234);
}

[Test]
public void IsLearningHubAccountLinked_returns_true_when_user_has_authid()
{
// Given
const int delegateId = 3;
const int learningHubAuthId = 1;

A.CallTo(() => userDataService.GetDelegateUserLearningHubAuthId(delegateId))
.Returns(learningHubAuthId);

// When
var result = learningHubLinkService.IsLearningHubAccountLinked(delegateId);

// Then
result.Should().BeTrue();
}

[Test]
public void DelegateUserLearningHubAccountIsLinked_returns_false_when_user_does_not_have_authid()
{
// Given
const int delegateId = 3;

A.CallTo(() => userDataService.GetDelegateUserLearningHubAuthId(delegateId))
.Returns(null);

// When
var result = learningHubLinkService.IsLearningHubAccountLinked(delegateId);

// Then
result.Should().BeFalse();
}

[Test]
public void LinkLearningHubAccountIfNotLinked_calls_service_to_update_delegate_authId_when_not_linked()
{
// Given
const int delegateId = 3;
const int learningHubAuthId = 1;

A.CallTo(() => userDataService.GetDelegateUserLearningHubAuthId(delegateId))
.Returns(null);

// When
learningHubLinkService.LinkLearningHubAccountIfNotLinked(delegateId, learningHubAuthId);

// Then
A.CallTo(() => userDataService.SetDelegateUserLearningHubAuthId(A<int>._, A<int>._))
.MustHaveHappenedOnceExactly();
}

[Test]
public void
LinkLearningHubAccountIfNotLinked_does_not_call_service_to_update_delegate_authId_when_already_linked()
{
// Given
const int delegateId = 3;
const int learningHubAuthId = 1;

A.CallTo(() => userDataService.GetDelegateUserLearningHubAuthId(delegateId))
.Returns(learningHubAuthId);

// When
learningHubLinkService.LinkLearningHubAccountIfNotLinked(delegateId, learningHubAuthId);

// Then
A.CallTo(() => userDataService.SetDelegateUserLearningHubAuthId(A<int>._, A<int>._))
.MustNotHaveHappened();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@

public class LearningHubSsoSecurityServiceTests
{
private IConfiguration Config { get; set; } = null!;
private const int TestTolerance = 3;
private const int TestIterations = 1000;
private const int TestLength = 3;
private IConfiguration Config { get; set; } = null!;

[SetUp]
public void Setup()
{
var clockService = A.Fake<IClockService>();
A.CallTo(() => clockService.UtcNow).Returns(new DateTime(2021, 12, 9, 8, 30, 45));
}

[OneTimeSetUp]
public void OneTimeSetUp()
Expand Down Expand Up @@ -121,7 +128,10 @@ public void GenerateHash_returns_different_hashes_for_different_secret_keys()
}

[Test]
public void VerifyHash_returns_true_for_hashed_created_within_tolerance_time([Range(-TestTolerance, TestTolerance, 1)] int delay)
public void VerifyHash_returns_true_for_hashed_created_within_tolerance_time(
[Range(-TestTolerance, TestTolerance, 1)]
int delay
)
{
// Given
var now = DateTime.UtcNow;
Expand All @@ -138,7 +148,10 @@ public void VerifyHash_returns_true_for_hashed_created_within_tolerance_time([Ra
}

[Test]
public void VerifyHash_returns_false_for_hashes_created_outside_tolerance_time([Values(-(TestTolerance+1), TestTolerance+1)] int delay)
public void VerifyHash_returns_false_for_hashes_created_outside_tolerance_time(
[Values(-(TestTolerance + 1), TestTolerance + 1)]
int delay
)
{
// Given
var now = DateTime.UtcNow;
Expand All @@ -153,7 +166,7 @@ public void VerifyHash_returns_false_for_hashes_created_outside_tolerance_time([
// Then
result.Should().BeFalse();
}

private class BinaryClockService : IClockService
{
public BinaryClockService(DateTime firstResult, DateTime secondResult)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,16 +397,6 @@ public void ActivateDelegateUser(int delegateId)
);
}

public int? GetDelegateUserLearningHubAuthId(int delegateId)
{
return connection.Query<int?>(
@"SELECT LearningHubAuthId
FROM Candidates
WHERE CandidateID = @delegateId",
new { delegateId }
).Single();
}

public void UpdateDelegateLhLoginWarningDismissalStatus(int delegateId, bool status)
{
connection.Execute(
Expand Down Expand Up @@ -450,5 +440,25 @@ FROM Candidates AS cd
new { aliasId }
);
}

public int? GetDelegateUserLearningHubAuthId(int delegateId)
{
return connection.Query<int?>(
@"SELECT LearningHubAuthId
FROM Candidates
WHERE CandidateID = @delegateId",
new { delegateId }
).Single();
}

public void SetDelegateUserLearningHubAuthId(int delegateId, int learningHubAuthId)
{
connection.Execute(
@"UPDATE Candidates
SET LearningHubAuthId = @learningHubAuthId
WHERE CandidateID = @delegateId",
new { delegateId, learningHubAuthId }
);
}
}
}
Loading