Type:
- @UtilityHelper.GetPrettifiedResourceTypeNameMoodle(UtilityHelper.ToEnum(item.ResourceType), 0)
+ @MoodleHelper.GetPrettifiedResourceTypeNameMoodle(UtilityHelper.ToEnum(item.ResourceType), 0)
@if (item.ResourceType != "moodle")
diff --git a/LearningHub.Nhs.WebUI/Views/Search/_SubmitFeedback.cshtml b/LearningHub.Nhs.WebUI/Views/Search/_SubmitFeedback.cshtml
index a1ab36e1a..317772449 100644
--- a/LearningHub.Nhs.WebUI/Views/Search/_SubmitFeedback.cshtml
+++ b/LearningHub.Nhs.WebUI/Views/Search/_SubmitFeedback.cshtml
@@ -1,5 +1,5 @@
@using Microsoft.AspNetCore.WebUtilities
-@model LearningHub.Nhs.WebUI.Models.Search.SearchResultViewModel
+@model LearningHub.Nhs.Shared.Models.Search.SearchResultViewModel
@{
var queryParams = QueryHelpers.ParseQuery(Context.Request.QueryString.ToString().ToLower());
diff --git a/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml b/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml
index 6b679b67e..c1dccf585 100644
--- a/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml
+++ b/LearningHub.Nhs.WebUI/Views/Shared/Tenant/LearningHub/_Layout.cshtml
@@ -51,11 +51,13 @@
@await Html.PartialAsync("_GoogleAnalytics")
+
Skip to main content
@@ -159,6 +161,7 @@
+
@RenderSection("Scripts", required: false)
diff --git a/LearningHub.Nhs.WebUI/Views/Shared/_TwitterFeeds.cshtml b/LearningHub.Nhs.WebUI/Views/Shared/_TwitterFeeds.cshtml
index 3ec036c6c..0d096a708 100644
--- a/LearningHub.Nhs.WebUI/Views/Shared/_TwitterFeeds.cshtml
+++ b/LearningHub.Nhs.WebUI/Views/Shared/_TwitterFeeds.cshtml
@@ -1,4 +1,4 @@
-@using LearningHub.Nhs.WebUI.Helpers;
+@using LearningHub.Nhs.Shared.Helpers;
@model List
diff --git a/LearningHub.Nhs.WebUI/Views/_ViewImports.cshtml b/LearningHub.Nhs.WebUI/Views/_ViewImports.cshtml
index 4af6553d8..b009df196 100644
--- a/LearningHub.Nhs.WebUI/Views/_ViewImports.cshtml
+++ b/LearningHub.Nhs.WebUI/Views/_ViewImports.cshtml
@@ -2,4 +2,4 @@
@using LearningHub.Nhs.WebUI.Models
@using LearningHub.Nhs.WebUI.Helpers
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
-@addTagHelper *, NHSUKViewComponents.Web
+@addTagHelper *, NHSUKViewComponents.Web
\ No newline at end of file
diff --git a/LearningHub.Nhs.WebUI/nuget.config.template b/LearningHub.Nhs.WebUI/nuget.config.template
new file mode 100644
index 000000000..dac496006
--- /dev/null
+++ b/LearningHub.Nhs.WebUI/nuget.config.template
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleConfig.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleConfig.cs
new file mode 100644
index 000000000..de178b6a2
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/Configuration/MoodleConfig.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LearningHub.Nhs.OpenApi.Models.Configuration
+{
+ ///
+ /// The Moodle Settings.
+ ///
+ public class MoodleConfig
+ {
+ ///
+ /// Gets or sets the base url for the Moodle service.
+ ///
+ public string APIBaseUrl { get; set; } = null!;
+
+ ///
+ /// Gets or sets the Web service Rest Format.
+ ///
+ public string APIWSRestFormat { get; set; } = null!;
+
+ ///
+ /// Gets or sets the token.
+ ///
+ public string APIWSToken { get; set; } = null!;
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj
index 727560e3f..e215135f9 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Models/LearningHub.Nhs.OpenApi.Models.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleHttpClient.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleHttpClient.cs
new file mode 100644
index 000000000..4a98b4ebf
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/HttpClients/IMoodleHttpClient.cs
@@ -0,0 +1,23 @@
+using System.Net.Http;
+using System.Threading.Tasks;
+
+namespace LearningHub.Nhs.OpenApi.Services.Interface.HttpClients
+{
+ ///
+ /// The Moodle Http Client interface.
+ ///
+ public interface IMoodleHttpClient
+ {
+ ///
+ /// The get cient async.
+ ///
+ /// The .
+ Task GetClient();
+
+ ///
+ /// GetDefaultParameters.
+ ///
+ /// defaultParameters.
+ string GetDefaultParameters();
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj
index aa019e18c..6fe3b2dfe 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/LearningHub.Nhs.OpenApi.Services.Interface.csproj
@@ -17,7 +17,7 @@
-
+
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleApiService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleApiService.cs
new file mode 100644
index 000000000..e366a4370
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services.Interface/Services/IMoodleApiService.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LearningHub.Nhs.OpenApi.Services.Interface.Services
+{
+ ///
+ /// IMoodleApiService.
+ ///
+ public interface IMoodleApiService
+ {
+ ///
+ /// GetResourcesAsync.
+ ///
+ /// The current LH User Id.
+ /// A representing the result of the asynchronous operation.
+ Task GetMoodleUserIdByUsernameAsync(int currentUserId);
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleHttpClient.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleHttpClient.cs
new file mode 100644
index 000000000..73af93977
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/HttpClients/MoodleHttpClient.cs
@@ -0,0 +1,95 @@
+using LearningHub.Nhs.OpenApi.Models.Configuration;
+using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LearningHub.Nhs.OpenApi.Services.HttpClients
+{
+ ///
+ /// The Moodle Http Client.
+ ///
+ public class MoodleHttpClient : IMoodleHttpClient, IDisposable
+ {
+ private readonly MoodleConfig moodleConfig;
+ 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, IOptions moodleConfig)
+ {
+ this.moodleConfig = moodleConfig.Value;
+ this.httpClient = httpClient;
+
+ this.moodleAPIBaseUrl = this.moodleConfig.APIBaseUrl + "webservice/rest/server.php";
+ this.moodleAPIMoodleWSRestFormat = this.moodleConfig.APIWSRestFormat;
+ this.moodleAPIWSToken = this.moodleConfig.APIWSToken;
+ }
+
+ ///
+ /// 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/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj
index 9002a0237..bf7b23c23 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/LearningHub.Nhs.OpenApi.Services.csproj
@@ -30,7 +30,7 @@
-
+
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs
new file mode 100644
index 000000000..90ffc4280
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Services/MoodleApiService.cs
@@ -0,0 +1,90 @@
+namespace LearningHub.Nhs.OpenApi.Services.Services
+{
+ using LearningHub.Nhs.Models.Moodle.API;
+ using LearningHub.Nhs.OpenApi.Services.Interface.HttpClients;
+ using LearningHub.Nhs.OpenApi.Services.Interface.Services;
+ using Microsoft.Extensions.Logging;
+ using Newtonsoft.Json;
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Net;
+ using System.Net.Http;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ ///
+ /// MoodleApiService.
+ ///
+ public class MoodleApiService : IMoodleApiService
+ {
+ private readonly IMoodleHttpClient moodleHttpClient;
+ private readonly ILogger logger;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// moodleHttpClient.
+ /// logger.
+ public MoodleApiService(IMoodleHttpClient moodleHttpClient, ILogger logger)
+ {
+ this.moodleHttpClient = moodleHttpClient;
+ this.logger = logger;
+ }
+ ///
+ /// GetMoodleUserIdByUsernameAsync.
+ ///
+ /// current User Id.
+ /// UserId from Moodle.
+ public async Task GetMoodleUserIdByUsernameAsync(int currentUserId)
+ {
+ var parameters = new Dictionary
+ {
+ { "criteria[0][key]", "username" },
+ { "criteria[0][value]", currentUserId.ToString() }
+ };
+
+ var response = await GetCallMoodleApiAsync("core_user_get_users", parameters);
+
+ var user = response?.Users?.FirstOrDefault(u => u.Username == currentUserId.ToString());
+ return user?.Id ?? 0;
+ }
+
+
+ private async Task GetCallMoodleApiAsync(string wsFunction, Dictionary parameters)
+ {
+ var client = await this.moodleHttpClient.GetClient();
+ string defaultParameters = this.moodleHttpClient.GetDefaultParameters();
+
+ // Build URL query
+ var queryBuilder = new StringBuilder();
+
+ queryBuilder.Append($"&wsfunction={wsFunction}");
+
+ foreach (var param in parameters)
+ {
+ queryBuilder.Append($"&{param.Key}={Uri.EscapeDataString(param.Value)}");
+ }
+
+ string fullUrl = "?" + defaultParameters + queryBuilder.ToString();
+
+ HttpResponseMessage response = await client.GetAsync(fullUrl);
+ string result = await response.Content.ReadAsStringAsync();
+
+ if (response.IsSuccessStatusCode)
+ {
+ return JsonConvert.DeserializeObject(result);
+ }
+ else if (response.StatusCode == HttpStatusCode.Unauthorized || response.StatusCode == HttpStatusCode.Forbidden)
+ {
+ this.logger.LogError($"Moodle API access denied. Status Code: {response.StatusCode}");
+ throw new Exception("AccessDenied to MoodleApi");
+ }
+ else
+ {
+ this.logger.LogError($"Moodle API error. Status Code: {response.StatusCode}, Message: {result}");
+ throw new Exception("Error with MoodleApi");
+ }
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs
index fb9098bde..f00f13253 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi.Services/Startup.cs
@@ -23,6 +23,7 @@ public static class Startup
public static void AddServices(this IServiceCollection services)
{
services.AddScoped();
+ services.AddHttpClient();
services.AddScoped();
services.AddScoped();
services.AddScoped();
@@ -33,6 +34,7 @@ public static void AddServices(this IServiceCollection services)
services.AddScoped();
services.AddScoped();
services.AddScoped();
+ services.AddScoped();
services.AddScoped();
services.AddScoped();
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs
index 63b61f042..7d5a61795 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs
+++ b/OpenAPI/LearningHub.Nhs.OpenApi/Configuration/ConfigurationExtensions.cs
@@ -40,6 +40,11 @@ public static class ConfigurationExtensions
///
public const string AzureSectionName = "Azure";
+ ///
+ /// The FindwiseSectionName.
+ ///
+ public const string MoodleSectionName = "Moodle";
+
///
/// Adds config.
///
@@ -58,6 +63,8 @@ public static void AddConfig(this IServiceCollection services, IConfiguration co
services.AddOptions().Bind(config.GetSection(LearningHubApiSectionName));
services.AddOptions().Bind(config.GetSection(AzureSectionName));
+
+ services.AddOptions().Bind(config.GetSection(MoodleSectionName));
}
private static OptionsBuilder RegisterPostConfigure(this OptionsBuilder builder)
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleController.cs b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleController.cs
new file mode 100644
index 000000000..30cb31a4e
--- /dev/null
+++ b/OpenAPI/LearningHub.Nhs.OpenApi/Controllers/MoodleController.cs
@@ -0,0 +1,47 @@
+namespace LearningHub.NHS.OpenAPI.Controllers
+{
+ using LearningHub.Nhs.OpenApi.Services.Interface.Services;
+ using Microsoft.AspNetCore.Authorization;
+ using Microsoft.AspNetCore.Mvc;
+ using System.Threading.Tasks;
+
+ ///
+ /// Moodle operations.
+ ///
+ [Route("Moodle")]
+ [ApiController]
+ [Authorize]
+ public class MoodleController : Controller
+ {
+ private readonly IMoodleApiService moodleService;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The moodle service.
+ public MoodleController(IMoodleApiService moodleService)
+ {
+ this.moodleService = moodleService;
+ }
+
+ ///
+ /// The GetMoodleUserId.
+ ///
+ /// The LH user id.
+ /// The .
+ [HttpGet]
+ [Route("GetMoodleUserId/{currentUserId?}")]
+ public async Task GetMoodleUserId(int? currentUserId)
+ {
+ if (currentUserId.HasValue)
+ {
+ var moodleUser = await this.moodleService.GetMoodleUserIdByUsernameAsync(currentUserId.Value);
+ return this.Ok(moodleUser);
+ }
+ else
+ {
+ return this.Ok(0);
+ }
+ }
+ }
+}
diff --git a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json
index 401183bf6..61417224f 100644
--- a/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json
+++ b/OpenAPI/LearningHub.Nhs.OpenApi/appsettings.json
@@ -119,5 +119,10 @@
"ResponseType": "code id_token",
"AuthSecret": "",
"AuthTimeout": 20
+ },
+ "Moodle": {
+ "APIBaseUrl": "",
+ "APIWSRestFormat": "json",
+ "APIWSToken": ""
}
}
diff --git a/global.json b/global.json
new file mode 100644
index 000000000..0974123a3
--- /dev/null
+++ b/global.json
@@ -0,0 +1,5 @@
+{
+ "sdk": {
+ "version": "8.0.412"
+ }
+}
\ No newline at end of file