diff --git a/Auth/LearningHub.Nhs.Auth.Tests/LearningHub.Nhs.Auth.Tests.csproj b/Auth/LearningHub.Nhs.Auth.Tests/LearningHub.Nhs.Auth.Tests.csproj index e52462d..ec6d6ad 100644 --- a/Auth/LearningHub.Nhs.Auth.Tests/LearningHub.Nhs.Auth.Tests.csproj +++ b/Auth/LearningHub.Nhs.Auth.Tests/LearningHub.Nhs.Auth.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/Auth/LearningHub.Nhs.Auth/Configuration/ServiceMappings.cs b/Auth/LearningHub.Nhs.Auth/Configuration/ServiceMappings.cs index 064aa10..79a6731 100644 --- a/Auth/LearningHub.Nhs.Auth/Configuration/ServiceMappings.cs +++ b/Auth/LearningHub.Nhs.Auth/Configuration/ServiceMappings.cs @@ -40,12 +40,22 @@ public static void AddServiceMappings(this IServiceCollection services, IConfigu ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, }); + + services.AddHttpClient() + .ConfigurePrimaryHttpMessageHandler( + () => new HttpClientHandler + { + ServerCertificateCustomValidationCallback = + HttpClientHandler.DangerousAcceptAnyServerCertificateValidator, + }); } else { services.AddHttpClient(); + services.AddHttpClient(); } + services.AddScoped(); services.AddDistributedMemoryCache(); services.AddScoped(); services.AddTransient(); diff --git a/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs b/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs index 4b4113d..0634fe6 100644 --- a/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs +++ b/Auth/LearningHub.Nhs.Auth/Configuration/WebSettings.cs @@ -61,5 +61,10 @@ public class WebSettings /// Gets or sets a value indicating whether IsPasswordUpdate. /// public bool IsPasswordUpdate { get; set; } - } + + /// + /// Gets or sets a value indicating whether gets or sets a value to Enable Moodle. + /// + public bool EnableMoodle { get; set; } + } } diff --git a/Auth/LearningHub.Nhs.Auth/Controllers/AccountController.cs b/Auth/LearningHub.Nhs.Auth/Controllers/AccountController.cs index 123fe1a..58f804d 100644 --- a/Auth/LearningHub.Nhs.Auth/Controllers/AccountController.cs +++ b/Auth/LearningHub.Nhs.Auth/Controllers/AccountController.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; + using Azure.Core; using elfhHub.Nhs.Models.Common; using elfhHub.Nhs.Models.Enums; using IdentityModel; @@ -22,9 +23,11 @@ using LearningHub.Nhs.Models.Common; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; + using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; + using UAParser; /// /// Account Controller operations. @@ -163,34 +166,44 @@ await this.interaction.GrantConsentAsync( if (loginResult.IsAuthenticated) { - await this.SignInUser(userId, model.Username.Trim(), model.RememberLogin, context.Parameters["ext_referer"]); - - if (context != null) + var uaParser = Parser.GetDefault(); + var clientInfo = uaParser.Parse(this.Request.Headers["User-Agent"]); + var result = await this.UserService.CheckUserHasAnActiveSessionAsync(userId); + if (result.Items.Count == 0 || result.Items[0].BrowserName == clientInfo.UA.Family) { - if (await this.ClientStore.IsPkceClientAsync(context.Client.ClientId)) + await this.SignInUser(userId, model.Username.Trim(), model.RememberLogin, context.Parameters["ext_referer"]); + + if (context != null) { - // if the client is PKCE then we assume it's native, so this change in how to - // return the response is for better UX for the end user. - return this.View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl }); + if (await this.ClientStore.IsPkceClientAsync(context.Client.ClientId)) + { + // if the client is PKCE then we assume it's native, so this change in how to + // return the response is for better UX for the end user. + return this.View("Redirect", new RedirectViewModel { RedirectUrl = model.ReturnUrl }); + } + + // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null + return this.Redirect(model.ReturnUrl); } - // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null - return this.Redirect(model.ReturnUrl); - } - - // request for a local page - if (this.Url.IsLocalUrl(model.ReturnUrl)) - { - return this.Redirect(model.ReturnUrl); - } - else if (string.IsNullOrEmpty(model.ReturnUrl)) - { - return this.Redirect("~/"); + // request for a local page + if (this.Url.IsLocalUrl(model.ReturnUrl)) + { + return this.Redirect(model.ReturnUrl); + } + else if (string.IsNullOrEmpty(model.ReturnUrl)) + { + return this.Redirect("~/"); + } + else + { + // user might have clicked on a malicious link - should be logged + throw new Exception("invalid return URL"); + } } else { - // user might have clicked on a malicious link - should be logged - throw new Exception("invalid return URL"); + return this.View("AlreadyActiveSession"); } } else if (userId > 0) diff --git a/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleApiService.cs b/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleApiService.cs new file mode 100644 index 0000000..81a3adc --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleApiService.cs @@ -0,0 +1,17 @@ +namespace LearningHub.Nhs.Auth.Interfaces +{ + using System.Threading.Tasks; + + /// + /// IMoodleApiService. + /// + public interface IMoodleApiService + { + /// + /// GetResourcesAsync. + /// + /// The current User Id. + /// A representing the result of the asynchronous operation. + Task GetMoodleUserIdByUsernameAsync(int currentUserId); + } +} diff --git a/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleHttpClient.cs b/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleHttpClient.cs new file mode 100644 index 0000000..1d711b8 --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Interfaces/IMoodleHttpClient.cs @@ -0,0 +1,23 @@ +namespace LearningHub.Nhs.Auth.Interfaces +{ + using System.Net.Http; + using System.Threading.Tasks; + + /// + /// The Moodle Http Client interface. + /// + public interface IMoodleHttpClient + { + /// + /// The get cient async. + /// + /// The . + Task GetClient(); + + /// + /// GetDefaultParameters. + /// + /// defaultParameters. + string GetDefaultParameters(); + } +} diff --git a/Auth/LearningHub.Nhs.Auth/Interfaces/IUserService.cs b/Auth/LearningHub.Nhs.Auth/Interfaces/IUserService.cs index 3a97b47..e4ae21c 100644 --- a/Auth/LearningHub.Nhs.Auth/Interfaces/IUserService.cs +++ b/Auth/LearningHub.Nhs.Auth/Interfaces/IUserService.cs @@ -114,6 +114,13 @@ public interface IUserService /// Task StoreUserHistoryAsync(UserHistoryViewModel userHistory); + /// + /// check user has an laredy active session. + /// + /// The userId. + /// The . + Task> CheckUserHasAnActiveSessionAsync(int userId); + /// /// The store user history async. /// diff --git a/Auth/LearningHub.Nhs.Auth/LearningHub.Nhs.Auth.csproj b/Auth/LearningHub.Nhs.Auth/LearningHub.Nhs.Auth.csproj index 01041c3..2933aee 100644 --- a/Auth/LearningHub.Nhs.Auth/LearningHub.Nhs.Auth.csproj +++ b/Auth/LearningHub.Nhs.Auth/LearningHub.Nhs.Auth.csproj @@ -101,7 +101,7 @@ - + diff --git a/Auth/LearningHub.Nhs.Auth/Models/MoodleUserResponseViewModel.cs b/Auth/LearningHub.Nhs.Auth/Models/MoodleUserResponseViewModel.cs new file mode 100644 index 0000000..fac745f --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Models/MoodleUserResponseViewModel.cs @@ -0,0 +1,121 @@ +namespace LearningHub.Nhs.Auth.Models +{ + using System.Collections.Generic; + + /// + /// MoodleUserResponseViewModel. + /// + public class MoodleUserResponseViewModel + { + /// + /// Gets or sets the list of users. + /// + public List Users { get; set; } + + /// + /// Gets or sets the warnings. + /// + public List Warnings { get; set; } + + /// + /// MoodleUser. + /// + public class MoodleUser + { + /// + /// Gets or sets the user ID. + /// + public int Id { get; set; } + + /// + /// Gets or sets the username. + /// + public string Username { get; set; } + + /// + /// Gets or sets the first name. + /// + public string FirstName { get; set; } + + /// + /// Gets or sets the last name. + /// + public string LastName { get; set; } + + /// + /// Gets or sets the full name. + /// + public string FullName { get; set; } + + /// + /// Gets or sets the email. + /// + public string Email { get; set; } + + /// + /// Gets or sets the department. + /// + public string Department { get; set; } + + /// + /// Gets or sets the first access timestamp. + /// + public long FirstAccess { get; set; } + + /// + /// Gets or sets the last access timestamp. + /// + public long LastAccess { get; set; } + + /// + /// Gets or sets the authentication method. + /// + public string Auth { get; set; } + + /// + /// Gets or sets a value indicating whether the user is suspended. + /// + public bool Suspended { get; set; } + + /// + /// Gets or sets a value indicating whether the user is confirmed. + /// + public bool Confirmed { get; set; } + + /// + /// Gets or sets the language. + /// + public string Lang { get; set; } + + /// + /// Gets or sets the theme. + /// + public string Theme { get; set; } + + /// + /// Gets or sets the timezone. + /// + public string Timezone { get; set; } + + /// + /// Gets or sets the mail format. + /// + public int MailFormat { get; set; } + + /// + /// Gets or sets the forum tracking preference. + /// + public int TrackForums { get; set; } + + /// + /// Gets or sets the small profile image URL. + /// + public string ProfileImageUrlSmall { get; set; } + + /// + /// Gets or sets the profile image URL. + /// + public string ProfileImageUrl { get; set; } + } + } +} diff --git a/Auth/LearningHub.Nhs.Auth/NLog.config b/Auth/LearningHub.Nhs.Auth/NLog.config index eb67b60..a59da11 100644 --- a/Auth/LearningHub.Nhs.Auth/NLog.config +++ b/Auth/LearningHub.Nhs.Auth/NLog.config @@ -39,6 +39,10 @@ + + + + diff --git a/Auth/LearningHub.Nhs.Auth/Services/MoodleApiService.cs b/Auth/LearningHub.Nhs.Auth/Services/MoodleApiService.cs new file mode 100644 index 0000000..8edb52e --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Services/MoodleApiService.cs @@ -0,0 +1,67 @@ +namespace LearningHub.Nhs.Auth.Services +{ + using System; + using System.Net.Http; + using System.Threading.Tasks; + using LearningHub.Nhs.Auth.Interfaces; + using LearningHub.Nhs.Auth.Models; + using Newtonsoft.Json; + + /// + /// MoodleApiService. + /// + public class MoodleApiService : IMoodleApiService + { + private readonly IMoodleHttpClient moodleHttpClient; + + /// + /// Initializes a new instance of the class. + /// + /// moodleHttpClient. + public MoodleApiService(IMoodleHttpClient moodleHttpClient) + { + this.moodleHttpClient = moodleHttpClient; + } + + /// + /// GetMoodleUserIdByUsernameAsync. + /// + /// current User Id. + /// UserId from Moodle. + public async Task GetMoodleUserIdByUsernameAsync(int currentUserId) + { + int moodleUserId = 0; + string additionalParameters = $"&criteria[0][key]=username&criteria[0][value]={currentUserId}"; + string defaultParameters = this.moodleHttpClient.GetDefaultParameters(); + + var client = await this.moodleHttpClient.GetClient(); + + string url = $"&wsfunction=core_user_get_users{additionalParameters}"; + + HttpResponseMessage response = await client.GetAsync("?" + defaultParameters + url); + if (response.IsSuccessStatusCode) + { + var result = response.Content.ReadAsStringAsync().Result; + var viewmodel = JsonConvert.DeserializeObject(result); + + if (viewmodel?.Users != null) + { + foreach (var user in viewmodel.Users) + { + if (user.Username == currentUserId.ToString()) + { + moodleUserId = user.Id; + } + } + } + } + else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized || + response.StatusCode == System.Net.HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return moodleUserId; + } + } +} diff --git a/Auth/LearningHub.Nhs.Auth/Services/MoodleHttpClient.cs b/Auth/LearningHub.Nhs.Auth/Services/MoodleHttpClient.cs new file mode 100644 index 0000000..5538136 --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Services/MoodleHttpClient.cs @@ -0,0 +1,87 @@ +namespace LearningHub.Nhs.Auth.Services +{ + using System; + using System.Net.Http; + using System.Net.Http.Headers; + using System.Threading.Tasks; + using LearningHub.Nhs.Auth.Interfaces; + using Microsoft.Extensions.Configuration; + + /// + /// The moodle http client. + /// + public class MoodleHttpClient : IMoodleHttpClient, IDisposable + { + private readonly HttpClient httpClient = new (); + private bool initialised = false; + private string moodleAPIBaseUrl; + private string moodleAPIMoodleWSRestFormat; + private string moodleAPIWSToken; + + /// + /// Initializes a new instance of the class. + /// + /// httpClient. + /// config. + public MoodleHttpClient(HttpClient httpClient, IConfiguration config) + { + this.httpClient = httpClient; + this.moodleAPIBaseUrl = config["MoodleAPIConfig:BaseUrl"]; + this.moodleAPIMoodleWSRestFormat = config["MoodleAPIConfig:MoodleWSRestFormat"]; + this.moodleAPIWSToken = config["MoodleAPIConfig:WSToken"]; + } + + /// + /// The Get Client method. + /// + /// The . + public async Task GetClient() + { + this.Initialise(this.moodleAPIBaseUrl); + return this.httpClient; + } + + /// + /// GetDefaultParameters. + /// + /// defaultParameters. + public string GetDefaultParameters() + { + string defaultParameters = $"wstoken={this.moodleAPIWSToken}" + + $"&moodlewsrestformat={this.moodleAPIMoodleWSRestFormat}"; + + return defaultParameters; + } + + /// + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// The dispoase. + /// + /// disposing. + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + this.httpClient.Dispose(); + } + } + + private void Initialise(string httpClientUrl) + { + if (this.initialised == false) + { + this.httpClient.BaseAddress = new Uri(httpClientUrl); + this.httpClient.DefaultRequestHeaders.Accept.Clear(); + this.httpClient.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/json")); + this.initialised = true; + } + } + } +} diff --git a/Auth/LearningHub.Nhs.Auth/Services/UserService.cs b/Auth/LearningHub.Nhs.Auth/Services/UserService.cs index 2ba58b7..98246ec 100644 --- a/Auth/LearningHub.Nhs.Auth/Services/UserService.cs +++ b/Auth/LearningHub.Nhs.Auth/Services/UserService.cs @@ -243,5 +243,29 @@ public async Task StoreUserHistoryAsync(UserHistoryViewModel userHistory) } } } + + /// + public async Task> CheckUserHasAnActiveSessionAsync(int userId) + { + PagedResultSet userHistoryViewModel = new PagedResultSet(); + + var client = this.UserApiHttpClient.GetClient(); + var request = $"UserHistory/CheckUserHasActiveSession/{userId}"; + var response = await client.GetAsync(request).ConfigureAwait(false); + + if (response.IsSuccessStatusCode) + { + var result = await response.Content.ReadAsStringAsync(); + userHistoryViewModel = JsonConvert.DeserializeObject>(result); + } + else if (response.StatusCode == HttpStatusCode.Unauthorized + || + response.StatusCode == HttpStatusCode.Forbidden) + { + throw new Exception("AccessDenied"); + } + + return userHistoryViewModel; + } } } diff --git a/Auth/LearningHub.Nhs.Auth/UserServices/LearningHubProfileService.cs b/Auth/LearningHub.Nhs.Auth/UserServices/LearningHubProfileService.cs index 5a3a602..9175d60 100644 --- a/Auth/LearningHub.Nhs.Auth/UserServices/LearningHubProfileService.cs +++ b/Auth/LearningHub.Nhs.Auth/UserServices/LearningHubProfileService.cs @@ -6,6 +6,7 @@ using IdentityServer4.Extensions; using IdentityServer4.Models; using IdentityServer4.Services; + using LearningHub.Nhs.Auth.Configuration; using LearningHub.Nhs.Auth.Interfaces; using Microsoft.Extensions.Logging; @@ -14,19 +15,29 @@ /// public class LearningHubProfileService : IProfileService { + private readonly WebSettings webSettings; + /// /// Initializes a new instance of the class. /// /// /// The user service. /// + /// + /// The moodle api service. + /// /// /// The logger. /// - public LearningHubProfileService(IUserService userService, ILogger logger) + /// + /// The webSettings. + /// + public LearningHubProfileService(IUserService userService, IMoodleApiService moodleApiService, ILogger logger, WebSettings webSettings) { this.UserService = userService; + this.MoodleApiService = moodleApiService; this.Logger = logger; + this.webSettings = webSettings; } /// @@ -39,6 +50,11 @@ public LearningHubProfileService(IUserService userService, ILogger protected IUserService UserService { get; } + /// + /// Gets the moodle api service. + /// + protected IMoodleApiService MoodleApiService { get; } + /// /// The get profile data async. /// @@ -65,6 +81,12 @@ public async Task GetProfileDataAsync(ProfileDataRequestContext context) new Claim("elfh_userName", user.UserName), }; + if (this.webSettings.EnableMoodle) + { + var moodleUser = await this.MoodleApiService.GetMoodleUserIdByUsernameAsync(user.Id); + claims.Add(new Claim("preferred_username", moodleUser.ToString())); + } + if (context.Subject.HasClaim("openAthensUser", "true")) { claims.Add(new Claim("openAthensUser", "true")); diff --git a/Auth/LearningHub.Nhs.Auth/Views/Account/AlreadyActiveSession.cshtml b/Auth/LearningHub.Nhs.Auth/Views/Account/AlreadyActiveSession.cshtml new file mode 100644 index 0000000..a0e908c --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/Views/Account/AlreadyActiveSession.cshtml @@ -0,0 +1,15 @@ +@{ + ViewData["Title"] = "Session already active"; +} +
+
+
+
+

@ViewData["Title"]

+

You are already logged in from another browser. Please continue using the same browser or close the existing session and try again with a new one.

+

If you have any questions, please contact the support team.

+

@DateTimeOffset.Now.ToString("d MMMM yyyy HH:mm:ss")

+
+
+
+
\ No newline at end of file diff --git a/Auth/LearningHub.Nhs.Auth/appsettings.json b/Auth/LearningHub.Nhs.Auth/appsettings.json index c54a92d..f4daca9 100644 --- a/Auth/LearningHub.Nhs.Auth/appsettings.json +++ b/Auth/LearningHub.Nhs.Auth/appsettings.json @@ -1,378 +1,384 @@ { - "Environment": "", - "ApplicationInsights": { - "InstrumentationKey": "" - }, - "AzureDataProtection": { - "StorageConnectionString": "", - "StorageContainerName": "learning-hub-id4", - "VaultKeyIdentifier": "", - "TenantId": "", - "ClientId": "", - "ClientSecret": "" - }, - "OpenAthensConfig": { - "Authority": "", - "ClientId": "", - "ClientSecret": "", - "RedirectUri": "" - }, - "Logging": { - "LogLevel": { - "Default": "Trace", - "Microsoft": "Trace" - } - }, - "ConnectionStrings": { - "NLogDb": "", - "Redis": "" - }, - "AllowedHosts": "*", - "WebSettings": { - "BuildNumber": "NotSet", - "UserApiUrl": "", - "X509Certificate2Thumbprint": "", - "LearningHubAdminUrl": "", - "elfhClientMvcUrl": "", - "LearningHubWebClient": "", - "AuthClientIdentityKey": "", - "ElfhHub": "", - "Rcr": "", - "SupportForm": "https://support.learninghub.nhs.uk/support/tickets/new", - "SupportFeedbackForm": "https://forms.office.com/e/C8tteweEhG", - "IsPasswordUpdate": "false" - }, - "AllowOpenAthensDebug": false, - "OaLhClients": { - "4A49B728-487A-49DC-92EE-B8A848AE13F5": "", - "97859211-1DBF-4CCA-B9EA-37940A6442D8": "", - "B28B1A31-45C1-484B-8E83-9D57CC1C4C7B": "", - "3584C984-028C-4002-AA4B-58AF665AEBDD": "", - "LearningHubOAClient": "" - }, - "OaScopes": [ "" ], - "AuthKey": "", - "AuthOrigin": "", - "IdentityServerCertThumbprint": "", - "LearningHubAuthConfig": { - "LearningHubClientSecrets": { - "LearningHubWebClient": "" + "Environment": "", + "ApplicationInsights": { + "InstrumentationKey": "" }, - "AuthClientIdentityKey": "", - "AuthTimeout": 20, - "AuthClients": { - "learninghubadmin": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "learninghubwebclient": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "migrationTool": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "", "" ], - "RedirectUris": [], - "PostLogoutUris": [], - "AllowedScopes": [ "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "learninghubwebclient_local": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "learninghubadmin_local": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": false, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": false, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": false - }, - "userprofileclient": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": true, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": true, - "RequireConsent": false, - "RequirePkce": true, - "AllowOfflineAccess": true - }, - "learninghubopenapi": { - "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": true, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": true, - "RequireConsent": false, - "RequirePkce": true, - "AllowOfflineAccess": true - }, - "digitallearningsolutions": { - "BaseUrl": "", - "ClientName": "", + "AzureDataProtection": { + "StorageConnectionString": "", + "StorageContainerName": "learning-hub-id4", + "VaultKeyIdentifier": "", + "TenantId": "", + "ClientId": "", + "ClientSecret": "" + }, + "OpenAthensConfig": { + "Authority": "", + "ClientId": "", "ClientSecret": "", - "AllowedGrantTypes": [ "" ], - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AllowedScopes": [ "", "", "", "", "" ], - "BackChannelLogoutSessionRequired": true, - "BackChannelLogoutUri": "", - "UpdateAccessTokenClaimsOnRefresh": true, - "RequireConsent": false, - "RequirePkce": true, - "AllowOfflineAccess": true - }, - "moodle": { + "RedirectUri": "" + }, + "Logging": { + "LogLevel": { + "Default": "Trace", + "Microsoft": "Trace" + } + }, + "ConnectionStrings": { + "NLogDb": "", + "Redis": "" + }, + "AllowedHosts": "*", + "WebSettings": { + "BuildNumber": "NotSet", + "UserApiUrl": "", + "X509Certificate2Thumbprint": "", + "LearningHubAdminUrl": "", + "elfhClientMvcUrl": "", + "LearningHubWebClient": "", + "AuthClientIdentityKey": "", + "ElfhHub": "", + "Rcr": "", + "SupportForm": "https://support.learninghub.nhs.uk/support/tickets/new", + "SupportFeedbackForm": "https://forms.office.com/e/C8tteweEhG", + "IsPasswordUpdate": "false", + "EnableMoodle": "false" + }, + "AllowOpenAthensDebug": false, + "OaLhClients": { + "4A49B728-487A-49DC-92EE-B8A848AE13F5": "", + "97859211-1DBF-4CCA-B9EA-37940A6442D8": "", + "B28B1A31-45C1-484B-8E83-9D57CC1C4C7B": "", + "3584C984-028C-4002-AA4B-58AF665AEBDD": "", + "LearningHubOAClient": "" + }, + "MoodleAPIConfig": { "BaseUrl": "", - "ClientName": "", - "ClientSecret": "", - "AllowedGrantTypes": [ "authorization_code" ], - "RedirectUris": [ "/auth/oidc/" ], - "PostLogoutUris": [ "/login/logout.php" ], - "AllowedScopes": [ "openid", "profile", "learninghubapi", "userapi", "roles", "learningcredentialsapi" ], - "BackChannelLogoutSessionRequired": true, - "BackChannelLogoutUri": "/login/logout.php", - "FrontChannelLogoutSessionRequired": true, - "FrontChannelLogoutUri": "/login/logout.php", - "UpdateAccessTokenClaimsOnRefresh": true, - "RequireConsent": false, - "RequirePkce": false, - "AllowOfflineAccess": true - } + "MoodleWSRestFormat": "json", + "WSToken": "" }, - "IdsClients": { - "eLfH": { - "ClientDescription": "e-Learning for Healthcare Hub", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "", "" ], - "Scopes": [ "openathens" ], - "AuthMainTitle": "e-Learning for Healthcare Authentication", - "ClientLogoSrc": "/images/client-logos/elfh.svg", - "ClientLogoAltText": "e-Learning for Healthcare", - "ClientCssClass": "elfh-hub", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "eIn": { - "ClientDescription": "eIntegrity", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "e-Integrity Authentication", - "ClientLogoSrc": "/images/client-logos/eInt.svg", - "ClientLogoAltText": "eIntegrity", - "ClientCssClass": "eIntegrity", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "UseRegister": false, - "RegisterAccountRelativeUrl": "", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "etft": { - "ClientDescription": "ETFT Educator Hub", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "Educator Hub Authentication", - "ClientLogoSrc": "/images/client-logos/etft-educator-hub.png", - "ClientLogoAltText": "ETFT Educator Hub", - "ClientCssClass": "etft", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "minded": { - "ClientDescription": "MindEd", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "MindEd Authentication", - "ClientLogoSrc": "/images/client-logos/minded.svg", - "ClientLogoAltText": "MindEd", - "ClientCssClass": "minded", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "dismat": { - "ClientDescription": "Disability Matters", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "Disability Matters Authentication", - "ClientLogoSrc": "/images/client-logos/disability-matters.png", - "ClientLogoAltText": "Disability Matters", - "ClientCssClass": "disability-matters", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "popwell": { - "ClientDescription": "Population Wellbeing Portal", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "Population Wellbeing Authentication", - "ClientLogoSrc": "/images/client-logos/population-wellbeing.png", - "ClientLogoAltText": "Population Wellbeing Portal", - "ClientCssClass": "population-wellbeing", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "volpass": { - "ClientDescription": "Volunteer Passport", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "VLP Authentication", - "ClientLogoSrc": "/images/client-logos/volpass.png", - "ClientLogoAltText": "Volunteers Passport", - "ClientCssClass": "vlp", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "carers": { - "ClientDescription": "Supporting Unpaid Carers", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [ "" ], - "PostLogoutUris": [ "" ], - "AuthMainTitle": "Supporting Unpaid Carers Authentication", - "ClientLogoSrc": "/images/client-logos/carers.svg", - "ClientLogoAltText": "Supporting Unpaid Carers", - "ClientCssClass": "carers", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false - }, - "learninghubadmin": { - "ClientDescription": "Learning Hub Admin App", - "AuthSecret": "", - "ClientUrl": "", - "RedirectUris": [], - "PostLogoutUris": [], - "AuthMainTitle": "Learning Hub Authentication", - "ClientLogoSrc": "/images/client-logos/learningHubAdmin.svg", - "ClientLogoUrl": "https://www.nhs.uk/", - "ClientLogoAltText": "Learning Hub Administration", - "ClientCssClass": "learning-hub", - "UseForgottenPassword": false, - "UseRegister": false, - "UseSupport": false, - "AllowRememberLogin": false, - "LayoutPath": "/Views/Shared/LearningHub/_Layout.cshtml" - }, - "learninghubwebclient": { - "ClientDescription": "Learning Hub", - "AuthSecret": "", - "ClientUrl": "", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "registration/create-an-account", - "RedirectUris": [], - "PostLogoutUris": [], - "AuthMainTitle": "Learning Hub", - "ClientLogoSrc": "/images/client-logos/nhs-learning-hub-beta.png", - "ClientLogoUrl": "https://www.nhs.uk/", - "ClientLogoAltText": "Learning Hub", - "ClientCssClass": "learning-hub", - "UseForgottenPassword": true, - "UseRegister": true, - "UseSupport": false, - "AllowRememberLogin": false, - "LayoutPath": "/Views/Shared/LearningHub/_Layout.cshtml" - }, - "digitallearningsolutions": { - "ClientDescription": "Learning Hub", - "ClientUrl": "", - "RedirectUris": [], - "PostLogoutUris": [], - "AuthMainTitle": "Digital Learning Solutions Authentication", - "ClientLogoSrc": "/images/client-logos/dls.svg", - "ClientLogoAltText": "Digital Learning Solutions", - "ClientCssClass": "learning-hub", - "ForgottenPasswordRelativeUrl": "forgotten-password", - "RegisterAccountRelativeUrl": "register", - "SupportUrl": "https://support.e-lfh.org.uk/", - "AllowRememberLogin": false, - "UseRegister": false - } + "OaScopes": [ "" ], + "AuthKey": "", + "AuthOrigin": "", + "IdentityServerCertThumbprint": "", + "LearningHubAuthConfig": { + "LearningHubClientSecrets": { + "LearningHubWebClient": "" + }, + "AuthClientIdentityKey": "", + "AuthTimeout": 20, + "AuthClients": { + "learninghubadmin": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "learninghubwebclient": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "migrationTool": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "", "" ], + "RedirectUris": [], + "PostLogoutUris": [], + "AllowedScopes": [ "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "learninghubwebclient_local": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "learninghubadmin_local": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": false, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": false, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": false + }, + "userprofileclient": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": true, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": true, + "RequireConsent": false, + "RequirePkce": true, + "AllowOfflineAccess": true + }, + "learninghubopenapi": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": true, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": true, + "RequireConsent": false, + "RequirePkce": true, + "AllowOfflineAccess": true + }, + "digitallearningsolutions": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "" ], + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AllowedScopes": [ "", "", "", "", "" ], + "BackChannelLogoutSessionRequired": true, + "BackChannelLogoutUri": "", + "UpdateAccessTokenClaimsOnRefresh": true, + "RequireConsent": false, + "RequirePkce": true, + "AllowOfflineAccess": true + }, + "moodle": { + "BaseUrl": "", + "ClientName": "", + "ClientSecret": "", + "AllowedGrantTypes": [ "authorization_code" ], + "RedirectUris": [ "/auth/oidc/" ], + "PostLogoutUris": [ "/login/logout.php" ], + "AllowedScopes": [ "openid", "profile", "learninghubapi", "userapi", "roles", "learningcredentialsapi" ], + "BackChannelLogoutSessionRequired": true, + "BackChannelLogoutUri": "/login/logout.php", + "FrontChannelLogoutSessionRequired": true, + "FrontChannelLogoutUri": "/login/logout.php", + "UpdateAccessTokenClaimsOnRefresh": true, + "RequireConsent": false, + "RequirePkce": false, + "AllowOfflineAccess": true + } + }, + "IdsClients": { + "eLfH": { + "ClientDescription": "e-Learning for Healthcare Hub", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "", "" ], + "Scopes": [ "openathens" ], + "AuthMainTitle": "e-Learning for Healthcare Authentication", + "ClientLogoSrc": "/images/client-logos/elfh.svg", + "ClientLogoAltText": "e-Learning for Healthcare", + "ClientCssClass": "elfh-hub", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "eIn": { + "ClientDescription": "eIntegrity", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "e-Integrity Authentication", + "ClientLogoSrc": "/images/client-logos/eInt.svg", + "ClientLogoAltText": "eIntegrity", + "ClientCssClass": "eIntegrity", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "UseRegister": false, + "RegisterAccountRelativeUrl": "", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "etft": { + "ClientDescription": "ETFT Educator Hub", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "Educator Hub Authentication", + "ClientLogoSrc": "/images/client-logos/etft-educator-hub.png", + "ClientLogoAltText": "ETFT Educator Hub", + "ClientCssClass": "etft", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "minded": { + "ClientDescription": "MindEd", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "MindEd Authentication", + "ClientLogoSrc": "/images/client-logos/minded.svg", + "ClientLogoAltText": "MindEd", + "ClientCssClass": "minded", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "dismat": { + "ClientDescription": "Disability Matters", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "Disability Matters Authentication", + "ClientLogoSrc": "/images/client-logos/disability-matters.png", + "ClientLogoAltText": "Disability Matters", + "ClientCssClass": "disability-matters", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "popwell": { + "ClientDescription": "Population Wellbeing Portal", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "Population Wellbeing Authentication", + "ClientLogoSrc": "/images/client-logos/population-wellbeing.png", + "ClientLogoAltText": "Population Wellbeing Portal", + "ClientCssClass": "population-wellbeing", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "volpass": { + "ClientDescription": "Volunteer Passport", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "VLP Authentication", + "ClientLogoSrc": "/images/client-logos/volpass.png", + "ClientLogoAltText": "Volunteers Passport", + "ClientCssClass": "vlp", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "carers": { + "ClientDescription": "Supporting Unpaid Carers", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [ "" ], + "PostLogoutUris": [ "" ], + "AuthMainTitle": "Supporting Unpaid Carers Authentication", + "ClientLogoSrc": "/images/client-logos/carers.svg", + "ClientLogoAltText": "Supporting Unpaid Carers", + "ClientCssClass": "carers", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false + }, + "learninghubadmin": { + "ClientDescription": "Learning Hub Admin App", + "AuthSecret": "", + "ClientUrl": "", + "RedirectUris": [], + "PostLogoutUris": [], + "AuthMainTitle": "Learning Hub Authentication", + "ClientLogoSrc": "/images/client-logos/learningHubAdmin.svg", + "ClientLogoUrl": "https://www.nhs.uk/", + "ClientLogoAltText": "Learning Hub Administration", + "ClientCssClass": "learning-hub", + "UseForgottenPassword": false, + "UseRegister": false, + "UseSupport": false, + "AllowRememberLogin": false, + "LayoutPath": "/Views/Shared/LearningHub/_Layout.cshtml" + }, + "learninghubwebclient": { + "ClientDescription": "Learning Hub", + "AuthSecret": "", + "ClientUrl": "", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "registration/create-an-account", + "RedirectUris": [], + "PostLogoutUris": [], + "AuthMainTitle": "Learning Hub", + "ClientLogoSrc": "/images/client-logos/nhs-learning-hub-beta.png", + "ClientLogoUrl": "https://www.nhs.uk/", + "ClientLogoAltText": "Learning Hub", + "ClientCssClass": "learning-hub", + "UseForgottenPassword": true, + "UseRegister": true, + "UseSupport": false, + "AllowRememberLogin": false, + "LayoutPath": "/Views/Shared/LearningHub/_Layout.cshtml" + }, + "digitallearningsolutions": { + "ClientDescription": "Learning Hub", + "ClientUrl": "", + "RedirectUris": [], + "PostLogoutUris": [], + "AuthMainTitle": "Digital Learning Solutions Authentication", + "ClientLogoSrc": "/images/client-logos/dls.svg", + "ClientLogoAltText": "Digital Learning Solutions", + "ClientCssClass": "learning-hub", + "ForgottenPasswordRelativeUrl": "forgotten-password", + "RegisterAccountRelativeUrl": "register", + "SupportUrl": "https://support.e-lfh.org.uk/", + "AllowRememberLogin": false, + "UseRegister": false + } + } } - } } \ No newline at end of file diff --git a/Auth/LearningHub.Nhs.Auth/package-lock.json b/Auth/LearningHub.Nhs.Auth/package-lock.json index 22d15bb..c8ba88f 100644 --- a/Auth/LearningHub.Nhs.Auth/package-lock.json +++ b/Auth/LearningHub.Nhs.Auth/package-lock.json @@ -25,13 +25,13 @@ "cross-env": "^7.0.3", "css-loader": "^5.2.4", "file-loader": "^6.2.0", - "sass": "^1.86.2", + "sass": "^1.86.3", "sass-loader": "^11.0.1", "style-loader": "^2.0.0", "ts-loader": "^9.5.2", "ts-node": "^10.2.0", "typescript": "^4.2.4", - "webpack": "^5.98.0", + "webpack": "^5.99.5", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.15.1" } @@ -5877,9 +5877,9 @@ "license": "MIT" }, "node_modules/sass": { - "version": "1.86.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.2.tgz", - "integrity": "sha512-Rpfn0zAIDqvnSb2DihJTDFjbhqLHu91Wqac9rxontWk7R+2txcPjuujMqu1eeoezh5kAblVCS5EdFdyr0Jmu+w==", + "version": "1.86.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.86.3.tgz", + "integrity": "sha512-iGtg8kus4GrsGLRDLRBRHY9dNVA78ZaS7xr01cWnS7PEMQyFtTqBiyCrfpTYTZXRWM94akzckYjh8oADfFNTzw==", "dev": true, "license": "MIT", "dependencies": { @@ -6909,9 +6909,9 @@ } }, "node_modules/webpack": { - "version": "5.98.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.98.0.tgz", - "integrity": "sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==", + "version": "5.99.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.99.5.tgz", + "integrity": "sha512-q+vHBa6H9qwBLUlHL4Y7L0L1/LlyBKZtS9FHNCQmtayxjI5RKC9yD8gpvLeqGv5lCQp1Re04yi0MF40pf30Pvg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/Auth/LearningHub.Nhs.Auth/package.json b/Auth/LearningHub.Nhs.Auth/package.json index 26249bf..fc266a9 100644 --- a/Auth/LearningHub.Nhs.Auth/package.json +++ b/Auth/LearningHub.Nhs.Auth/package.json @@ -35,13 +35,13 @@ "cross-env": "^7.0.3", "css-loader": "^5.2.4", "file-loader": "^6.2.0", - "sass": "^1.86.2", + "sass": "^1.86.3", "sass-loader": "^11.0.1", "style-loader": "^2.0.0", "ts-loader": "^9.5.2", "ts-node": "^10.2.0", "typescript": "^4.2.4", - "webpack": "^5.98.0", + "webpack": "^5.99.5", "webpack-cli": "^4.10.0", "webpack-dev-server": "^4.15.1" } diff --git a/Auth/LearningHub.Nhs.Auth/web.config b/Auth/LearningHub.Nhs.Auth/web.config new file mode 100644 index 0000000..0cd2434 --- /dev/null +++ b/Auth/LearningHub.Nhs.Auth/web.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Hee.UserProfile.Database/Hee.UserProfile.Database.sqlproj b/Hee.UserProfile.Database/Hee.UserProfile.Database.sqlproj index b8cf3b5..df6c02e 100644 --- a/Hee.UserProfile.Database/Hee.UserProfile.Database.sqlproj +++ b/Hee.UserProfile.Database/Hee.UserProfile.Database.sqlproj @@ -16,7 +16,7 @@ 1033, CI BySchemaAndSchemaType True - v4.5.2 + v4.8 CS Properties False diff --git a/LearningHub.Nhs.UserApi.Repository.Interface/IUserHistoryRepository.cs b/LearningHub.Nhs.UserApi.Repository.Interface/IUserHistoryRepository.cs index e72aebf..8684ba8 100644 --- a/LearningHub.Nhs.UserApi.Repository.Interface/IUserHistoryRepository.cs +++ b/LearningHub.Nhs.UserApi.Repository.Interface/IUserHistoryRepository.cs @@ -59,5 +59,12 @@ public interface IUserHistoryRepository /// The . /// Task GetPagedByUserIdAsync(int userId, int startPage, int pageSize); + + /// + /// Check user has an active login session. + /// + /// The userId. + /// The . + Task CheckUserHasActiveSessionAsync(int userId); } } \ No newline at end of file diff --git a/LearningHub.Nhs.UserApi.Repository.Interface/LearningHub.Nhs.UserApi.Repository.Interface.csproj b/LearningHub.Nhs.UserApi.Repository.Interface/LearningHub.Nhs.UserApi.Repository.Interface.csproj index fc69964..29a3a90 100644 --- a/LearningHub.Nhs.UserApi.Repository.Interface/LearningHub.Nhs.UserApi.Repository.Interface.csproj +++ b/LearningHub.Nhs.UserApi.Repository.Interface/LearningHub.Nhs.UserApi.Repository.Interface.csproj @@ -8,7 +8,7 @@ - + all diff --git a/LearningHub.Nhs.UserApi.Repository/LearningHub.Nhs.UserApi.Repository.csproj b/LearningHub.Nhs.UserApi.Repository/LearningHub.Nhs.UserApi.Repository.csproj index 4644295..5921669 100644 --- a/LearningHub.Nhs.UserApi.Repository/LearningHub.Nhs.UserApi.Repository.csproj +++ b/LearningHub.Nhs.UserApi.Repository/LearningHub.Nhs.UserApi.Repository.csproj @@ -8,7 +8,7 @@ - + diff --git a/LearningHub.Nhs.UserApi.Repository/UserHistoryRepository.cs b/LearningHub.Nhs.UserApi.Repository/UserHistoryRepository.cs index 673a3ae..3f0386b 100644 --- a/LearningHub.Nhs.UserApi.Repository/UserHistoryRepository.cs +++ b/LearningHub.Nhs.UserApi.Repository/UserHistoryRepository.cs @@ -9,6 +9,7 @@ using LearningHub.Nhs.UserApi.Repository.Interface; using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; + using Newtonsoft.Json.Linq; /// /// The user history repository. @@ -66,11 +67,13 @@ public async Task CreateAsync(int userId, int tenantId, UserHistoryViewModel use new SqlParameter("@LoginIP", SqlDbType.VarChar) { Value = userHistoryVM.LoginIP ?? (object)DBNull.Value }, new SqlParameter("@LoginSuccessFul", SqlDbType.Bit) { Value = userHistoryVM.LoginSuccessFul ?? (object)DBNull.Value }, new SqlParameter("@TenantId", SqlDbType.Int) { Value = tenantId }, + new SqlParameter("@SessionId", SqlDbType.VarChar) { Value = (userHistoryVM.UserHistoryTypeId == 0 && userHistoryVM.Detail == "User logged on. Source of auth: LearningHub.Nhs.Auth Account\\Login") ? userHistoryVM.SessionId : (object)DBNull.Value }, + new SqlParameter("@IsActive", SqlDbType.Bit) { Value = (userHistoryVM.UserHistoryTypeId == 0 && userHistoryVM.Detail == "User logged on. Source of auth: LearningHub.Nhs.Auth Account\\Login") ? userHistoryVM.IsActive : (object)DBNull.Value }, new SqlParameter("@AmendUserId", SqlDbType.Int) { Value = userId }, new SqlParameter("@AmendDate", SqlDbType.DateTimeOffset) { Value = DateTimeOffset.Now }, }; - string sql = "proc_UserHistoryInsert @UserId, @UserHistoryTypeId, @Detail, @UserAgent, @BrowserName, @BrowserVersion, @UrlReferer, @LoginIP, @LoginSuccessFul, @TenantId, @AmendUserId, @AmendDate"; + string sql = "proc_UserHistoryInsert @UserId, @UserHistoryTypeId, @Detail, @UserAgent, @BrowserName, @BrowserVersion, @UrlReferer, @LoginIP, @LoginSuccessFul, @TenantId, @SessionId, @IsActive, @AmendUserId, @AmendDate"; await this.DbContext.Database.ExecuteSqlRawAsync(sql, sqlParams); } @@ -98,5 +101,24 @@ public async Task GetPagedByUserIdAsync(int userId return retVal; } + + /// + public async Task CheckUserHasActiveSessionAsync(int userId) + { + try + { + var retVal = new UserHistoryStoredProcResults(); + var param0 = new SqlParameter("@p0", SqlDbType.Int) { Value = userId }; + + var result = await this.DbContext.Set().FromSqlRaw( + "dbo.proc_ActiveLearningHubUserbyId @p0", param0).AsNoTracking().ToListWithNoLockAsync(); + retVal.Results = result; + return retVal; + } + catch (Exception ex) + { + return null; + } + } } } \ No newline at end of file diff --git a/LearningHub.Nhs.UserApi.Services.Interface/IUserHistoryService.cs b/LearningHub.Nhs.UserApi.Services.Interface/IUserHistoryService.cs index 7ed5e01..9c6954b 100644 --- a/LearningHub.Nhs.UserApi.Services.Interface/IUserHistoryService.cs +++ b/LearningHub.Nhs.UserApi.Services.Interface/IUserHistoryService.cs @@ -53,5 +53,12 @@ public interface IUserHistoryService /// The . /// Task> GetUserHistoryPageAsync(int page, int pageSize, string sortColumn = "", string sortDirection = "", string presetFilter = "", string filter = ""); + + /// + /// Check user has an active login session. + /// + /// The userId. + /// The . + Task> CheckUserHasActiveSessionAsync(int userId); } } diff --git a/LearningHub.Nhs.UserApi.Services.Interface/LearningHub.Nhs.UserAPI.Services.Interface.csproj b/LearningHub.Nhs.UserApi.Services.Interface/LearningHub.Nhs.UserAPI.Services.Interface.csproj index fc69964..29a3a90 100644 --- a/LearningHub.Nhs.UserApi.Services.Interface/LearningHub.Nhs.UserAPI.Services.Interface.csproj +++ b/LearningHub.Nhs.UserApi.Services.Interface/LearningHub.Nhs.UserAPI.Services.Interface.csproj @@ -8,7 +8,7 @@ - + all diff --git a/LearningHub.Nhs.UserApi.Services.UnitTests/LearningHub.Nhs.UserApi.Services.UnitTests.csproj b/LearningHub.Nhs.UserApi.Services.UnitTests/LearningHub.Nhs.UserApi.Services.UnitTests.csproj index 78785b5..a61a661 100644 --- a/LearningHub.Nhs.UserApi.Services.UnitTests/LearningHub.Nhs.UserApi.Services.UnitTests.csproj +++ b/LearningHub.Nhs.UserApi.Services.UnitTests/LearningHub.Nhs.UserApi.Services.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/LearningHub.Nhs.UserApi.Services/LearningHub.Nhs.UserApi.Services.csproj b/LearningHub.Nhs.UserApi.Services/LearningHub.Nhs.UserApi.Services.csproj index 0b91349..670491b 100644 --- a/LearningHub.Nhs.UserApi.Services/LearningHub.Nhs.UserApi.Services.csproj +++ b/LearningHub.Nhs.UserApi.Services/LearningHub.Nhs.UserApi.Services.csproj @@ -8,7 +8,7 @@ - + diff --git a/LearningHub.Nhs.UserApi.Services/UserHistoryService.cs b/LearningHub.Nhs.UserApi.Services/UserHistoryService.cs index c65377c..e6ef86c 100644 --- a/LearningHub.Nhs.UserApi.Services/UserHistoryService.cs +++ b/LearningHub.Nhs.UserApi.Services/UserHistoryService.cs @@ -1,5 +1,6 @@ namespace LearningHub.Nhs.UserApi.Services { + using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -56,6 +57,8 @@ public async Task CreateAsync(UserHistoryViewModel if (retVal.IsValid) { + userHistoryVM.SessionId = Guid.NewGuid().ToString(); + userHistoryVM.IsActive = true; await this.userHistoryRepository.CreateAsync(userHistoryVM.UserId, this.settings.LearningHubTenantId, userHistoryVM); } @@ -99,6 +102,16 @@ public async Task> GetUserHistoryPageAsync( return result; } + /// + public async Task> CheckUserHasActiveSessionAsync(int userId) + { + PagedResultSet result = new PagedResultSet(); + var userHistory = await this.userHistoryRepository.CheckUserHasActiveSessionAsync(userId); + userHistory.Results.ForEach(x => x.UserAgent = this.ParseUserAgentString(x.UserAgent)); + result.Items = this.mapper.Map>(userHistory.Results); + return result; + } + private string ParseUserAgentString(string userAgent) { string retVal = string.Empty; diff --git a/LearningHub.Nhs.UserApi.Shared/LearningHub.Nhs.UserApi.Shared.csproj b/LearningHub.Nhs.UserApi.Shared/LearningHub.Nhs.UserApi.Shared.csproj index 149be25..ecfe311 100644 --- a/LearningHub.Nhs.UserApi.Shared/LearningHub.Nhs.UserApi.Shared.csproj +++ b/LearningHub.Nhs.UserApi.Shared/LearningHub.Nhs.UserApi.Shared.csproj @@ -8,7 +8,7 @@ - + all diff --git a/LearningHub.Nhs.UserApi.UnitTests/LearningHub.Nhs.UserApi.UnitTests.csproj b/LearningHub.Nhs.UserApi.UnitTests/LearningHub.Nhs.UserApi.UnitTests.csproj index fda3b53..5c215c5 100644 --- a/LearningHub.Nhs.UserApi.UnitTests/LearningHub.Nhs.UserApi.UnitTests.csproj +++ b/LearningHub.Nhs.UserApi.UnitTests/LearningHub.Nhs.UserApi.UnitTests.csproj @@ -10,7 +10,7 @@ - + diff --git a/LearningHub.Nhs.UserApi/Controllers/UserHistoryController.cs b/LearningHub.Nhs.UserApi/Controllers/UserHistoryController.cs index f86d769..d1436d4 100644 --- a/LearningHub.Nhs.UserApi/Controllers/UserHistoryController.cs +++ b/LearningHub.Nhs.UserApi/Controllers/UserHistoryController.cs @@ -100,6 +100,19 @@ public async Task GetUserHistoryPageAsync(int page, int pageSize, return this.Ok(pagedResultSet); } + /// + /// Check the user has an active login session. + /// + /// The UserId. + /// The . + [HttpGet] + [Route("CheckUserHasActiveSession/{userId}")] + public async Task CheckUserHasActiveSessionAsync(int userId) + { + PagedResultSet pagedResultSet = await this.userHistoryService.CheckUserHasActiveSessionAsync(userId); + return this.Ok(pagedResultSet); + } + /// /// Create a UserHistory. /// diff --git a/LearningHub.Nhs.UserApi/LearningHub.Nhs.UserApi.csproj b/LearningHub.Nhs.UserApi/LearningHub.Nhs.UserApi.csproj index 50f8813..c707f5a 100644 --- a/LearningHub.Nhs.UserApi/LearningHub.Nhs.UserApi.csproj +++ b/LearningHub.Nhs.UserApi/LearningHub.Nhs.UserApi.csproj @@ -23,7 +23,7 @@ - + diff --git a/LearningHub.Nhs.UserApi/Program.cs b/LearningHub.Nhs.UserApi/Program.cs index 8a6e0aa..c82ae49 100644 --- a/LearningHub.Nhs.UserApi/Program.cs +++ b/LearningHub.Nhs.UserApi/Program.cs @@ -11,6 +11,7 @@ var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger(); var csp = "object-src 'none'; frame-ancestors 'none'; sandbox allow-forms allow-same-origin allow-scripts allow-popups; base-uri 'self';"; + try { logger.Debug("Log Started"); diff --git a/LearningHub.Nhs.UserApi/web.config b/LearningHub.Nhs.UserApi/web.config new file mode 100644 index 0000000..f1d8e42 --- /dev/null +++ b/LearningHub.Nhs.UserApi/web.config @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file