Skip to content

Commit d572888

Browse files
committed
fixes
1 parent 076bce6 commit d572888

File tree

12 files changed

+116
-40
lines changed

12 files changed

+116
-40
lines changed

github-monitor/Ahk.GitHub.Monitor/GitHubMonitorFunction.cs

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
using Ahk.GitHub.Monitor.EventHandlers.BaseAndUtils;
77
using Ahk.GitHub.Monitor.Helpers;
88
using Ahk.GitHub.Monitor.Services.EventDispatch;
9+
using Azure.Identity;
10+
using Azure.Security.KeyVault.Secrets;
911
using Microsoft.AspNetCore.Http;
1012
using Microsoft.AspNetCore.Mvc;
1113
using Microsoft.Azure.Functions.Worker;
@@ -26,6 +28,13 @@ public async Task<IActionResult> Run(
2628
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)]
2729
HttpRequestData request)
2830
{
31+
string keyVaultUrl = Environment.GetEnvironmentVariable("KEY_VAULT_URI");
32+
if (keyVaultUrl == null)
33+
{
34+
return new BadRequestObjectResult(new { error = "Please set environment variable KEY_VAULT_URI" });
35+
}
36+
var secretClient = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential());
37+
2938
request.Headers.TryGetValues("X-GitHub-Event", out IEnumerable<string> eventNameValues);
3039
var eventName = eventNameValues?.FirstOrDefault();
3140
request.Headers.TryGetValues("X-GitHub-Delivery", out IEnumerable<string> deliveryIdValues);
@@ -42,6 +51,11 @@ public async Task<IActionResult> Run(
4251
return new BadRequestObjectResult(new { error = "X-GitHub-Event header missing" });
4352
}
4453

54+
if (eventName == "ping")
55+
{
56+
return new OkObjectResult("pong");
57+
}
58+
4559
if (string.IsNullOrEmpty(receivedSignature))
4660
{
4761
return new BadRequestObjectResult(new { error = "X-Hub-Signature-256 header missing" });
@@ -56,19 +70,21 @@ public async Task<IActionResult> Run(
5670

5771
var orgName = parsedRequestBody.Repository.Owner.Login;
5872

59-
var orgConfig = new GitHubMonitorConfig();
60-
configuration.GetSection(GitHubMonitorConfig.GetSectionName(orgName)).Bind(orgConfig);
73+
var githubAppId = await secretClient.GetSecretAsync($"GitHubMonitorConfig--{orgName}--GitHubAppId");
74+
var githubAppPrivateKey = await secretClient.GetSecretAsync($"GitHubMonitorConfig--{orgName}--GitHubAppPrivateKey");
75+
var githubWebhookSecret = await secretClient.GetSecretAsync($"GitHubMonitorConfig--{orgName}--GitHubWebhookSecret");
76+
6177

62-
if (string.IsNullOrEmpty(orgConfig.GitHubWebhookSecret))
78+
if (string.IsNullOrEmpty(githubWebhookSecret.Value.Value))
6379
{
6480
return new ObjectResult(new { error = "GitHub secret not configured" })
6581
{
6682
StatusCode = StatusCodes.Status500InternalServerError
6783
};
6884
}
6985

70-
if (string.IsNullOrEmpty(orgConfig.GitHubAppId) ||
71-
string.IsNullOrEmpty(orgConfig.GitHubAppPrivateKey))
86+
if (string.IsNullOrEmpty(githubAppId.Value.Value) ||
87+
string.IsNullOrEmpty(githubAppPrivateKey.Value.Value))
7288
{
7389
return new ObjectResult(new { error = "GitHub App ID/Token not configured" })
7490
{
@@ -77,7 +93,7 @@ public async Task<IActionResult> Run(
7793
}
7894

7995
if (!GitHubSignatureValidator.IsSignatureValid(requestBody, receivedSignature,
80-
orgConfig.GitHubWebhookSecret))
96+
githubWebhookSecret.Value.Value))
8197
{
8298
return new BadRequestObjectResult(new { error = "Payload signature not valid" });
8399
}

grade-management-new/GradeManagement.Bll/Services/AssignmentEventProcessorService.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using GradeManagement.Shared.Dtos.AssignmentEvents;
66
using GradeManagement.Shared.Enums;
77

8+
using Microsoft.EntityFrameworkCore;
89
using Microsoft.IdentityModel.Tokens;
910

1011
using Assignment = GradeManagement.Shared.Dtos.Assignment;
@@ -38,6 +39,20 @@ public async Task ConsumeAssignmentAcceptedEventAsync(AssignmentAccepted assignm
3839
await using var transaction = await gradeManagementDbContext.Database.BeginTransactionAsync();
3940
try
4041
{
42+
var existingAssignment = await gradeManagementDbContext.Assignment.Where(
43+
a => a.GithubRepoUrl == assignmentAccepted.GitHubRepositoryUrl).FirstOrDefaultAsync();
44+
if (existingAssignment != null)
45+
{
46+
var assignmentLogForExistingAssingnment = new AssignmentLog()
47+
{
48+
EventType = EventType.AssignmentAccepted,
49+
Description = $"Assignment for github repo url {assignmentAccepted.GitHubRepositoryUrl} already exists!",
50+
AssignmentId = existingAssignment.Id
51+
};
52+
await assignmentLogService.CreateAsync(assignmentLogForExistingAssingnment);
53+
return;
54+
}
55+
4156
var repositoryName = GetRepositoryNameFromUrl(assignmentAccepted.GitHubRepositoryUrl);
4257
var exercise = await exerciseService.GetExerciseModelByGitHubRepoNameWithoutQfAsync(repositoryName);
4358
var studentGitHubId = repositoryName.Remove(0, (exercise.GithubPrefix + "-").Length);

grade-management-new/GradeManagement.Bll/Services/Moodle/MoodleIntegrationService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public async Task UploadScore(Score score)
3232
var scoreType = score.ScoreType;
3333
if (student.MoodleId == null) throw new MoodleSyncException("No moodle ID for student");
3434

35-
var token = tokenGeneratorService.GenerateAccessToken(course);
35+
var token = await tokenGeneratorService.GenerateAccessToken(course);
3636

3737
if (token == null) throw new MoodleSyncException("Token was null when trying to register score");
3838
var client = new HttpClient();
@@ -42,6 +42,7 @@ public async Task UploadScore(Score score)
4242
{
4343
Timestamp = DateTimeOffset.Now.ToString("O"),
4444
ScoreGiven = Convert.ToInt32(score.Value),
45+
ScoreMaximum = 100,
4546
UserId = student.MoodleId,
4647
ActivityProgress = "Completed",
4748
GradingProgress = "FullyGraded"

grade-management-new/GradeManagement.Bll/Services/Moodle/TokenGeneratorService.cs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
using Azure.Identity;
2+
using Azure.Security.KeyVault.Secrets;
3+
14
using GradeManagement.Data.Models;
25
using GradeManagement.Shared.Config;
36
using GradeManagement.Shared.Exceptions;
@@ -22,9 +25,9 @@ public class TokenGeneratorService(IConfiguration configuration)
2225
private const string Scope =
2326
"https://purl.imsglobal.org/spec/lti-ags/scope/lineitem https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly https://purl.imsglobal.org/spec/lti-ags/scope/score";
2427

25-
public string? GenerateAccessToken(Course course)
28+
public async Task<string?> GenerateAccessToken(Course course)
2629
{
27-
var token = MakeClientAssertionToken(course);
30+
var token = await MakeClientAssertionToken(course);
2831

2932
var endPoint = "https://edu.vik.bme.hu/mod/lti/token.php";
3033
var client = new HttpClient();
@@ -43,7 +46,7 @@ public class TokenGeneratorService(IConfiguration configuration)
4346
return content?.Access_token;
4447
}
4548

46-
private string MakeClientAssertionToken(Course course)
49+
private async Task<string> MakeClientAssertionToken(Course course)
4750
{
4851
var appUrl = configuration["APP_URL"];
4952
if (string.IsNullOrEmpty(appUrl)) throw new MoodleSyncException("App url was null or empty!");
@@ -56,14 +59,22 @@ private string MakeClientAssertionToken(Course course)
5659
claims.Add(new Claim("aud", "https://edu.vik.bme.hu/mod/lti/token.php"));
5760
claims.Add(new Claim("sub", course.MoodleClientId));
5861

59-
return CreateToken(claims, course);
62+
return await CreateToken(claims, course);
6063
}
6164

62-
private string CreateToken(List<Claim> claims, Course course)
65+
private async Task<string> CreateToken(List<Claim> claims, Course course)
6366
{
64-
var moodleConfig = new MoodleConfig();
65-
configuration.GetSection(MoodleConfig.GetSectionName(course.MoodleClientId)).Bind(moodleConfig);
66-
var privateRsaKey = moodleConfig.MoodlePrivateKey;
67+
string keyVaultUrl = Environment.GetEnvironmentVariable("KEY_VAULT_URI");
68+
if (keyVaultUrl == null)
69+
{
70+
throw new Exception("Please set environment variable KEY_VAULT_URI");
71+
}
72+
73+
var secretClient = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential());
74+
var moodlePrivateKey =
75+
await secretClient.GetSecretAsync($"{MoodleConfig.Name}--{course.MoodleClientId}--MoodlePrivateKey");
76+
77+
var privateRsaKey = moodlePrivateKey.Value.Value;
6778
if (string.IsNullOrEmpty(privateRsaKey)) throw new MoodleSyncException("Private RSA was null or empty!");
6879

6980
privateRsaKey = privateRsaKey.Trim();

grade-management-new/GradeManagement.Bll/Services/Utils/RsaKeyGenerator.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,14 @@ private string ExportPrivateKey(RSA rsa)
3333

3434
private string ExportPublicKey(RSA rsa)
3535
{
36-
var publicKeyBytes = rsa.ExportRSAPublicKey();
36+
var publicKeyBytes = rsa.ExportSubjectPublicKeyInfo();
3737
var base64PublicKey = Convert.ToBase64String(publicKeyBytes);
3838
var sb = new StringBuilder();
3939
sb.AppendLine("-----BEGIN PUBLIC KEY-----");
4040
for (int i = 0; i < base64PublicKey.Length; i += 64)
4141
{
4242
sb.AppendLine(base64PublicKey.Substring(i, Math.Min(64, base64PublicKey.Length - i)));
4343
}
44-
4544
sb.AppendLine("-----END PUBLIC KEY-----");
4645
return sb.ToString();
4746
}

grade-management-new/GradeManagement.Client/Pages/CreationWizard.razor

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
@inject LanguageClient LanguageClient
1212
@inject SemesterClient SemesterClient
1313
@inject CourseClient CourseClient
14+
@inject HttpClient Http
1415
@inject NavigationManager NavigationManager
1516
@inject IJSRuntime JSRuntime
1617
@attribute [Authorize(Policy = Policy.RequireTeacher)]
@@ -313,8 +314,9 @@
313314
{
314315
try
315316
{
316-
// Create proper manifest with required fields
317-
GitHubAppManifest gitHubAppManifest = new();
317+
string appUrl = await Http.GetStringAsync("api/config/app-url");
318+
string monitorUrl = await Http.GetStringAsync("api/config/monitor-url");
319+
GitHubAppManifest gitHubAppManifest = new(appUrl, monitorUrl);
318320

319321
var manifestJson = JsonSerializer.Serialize(gitHubAppManifest);
320322

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
3+
namespace GradeManagement.Server.Controllers;
4+
5+
[ApiController]
6+
[Route("api/config")]
7+
public class ConfigController : ControllerBase
8+
{
9+
[HttpGet("app-url")]
10+
[ProducesResponseType(StatusCodes.Status200OK)]
11+
[ProducesResponseType(StatusCodes.Status404NotFound)]
12+
public IActionResult GetAppUrl()
13+
{
14+
var appUrl = Environment.GetEnvironmentVariable("APP_URL");
15+
16+
if (string.IsNullOrEmpty(appUrl))
17+
{
18+
return NotFound("APP_URL is not set.");
19+
}
20+
21+
return Ok(appUrl);
22+
}
23+
24+
[HttpGet("monitor-url")]
25+
[ProducesResponseType(StatusCodes.Status200OK)]
26+
[ProducesResponseType(StatusCodes.Status404NotFound)]
27+
public IActionResult GetMonitorUrl()
28+
{
29+
var monitorUrl = Environment.GetEnvironmentVariable("MONITOR_URL");
30+
31+
if (string.IsNullOrEmpty(monitorUrl))
32+
{
33+
return NotFound("MONITOR_URL is not set.");
34+
}
35+
36+
return Ok(monitorUrl);
37+
}
38+
}

grade-management-new/GradeManagement.Server/Controllers/GitHubAppController.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Azure.Identity;
22
using Azure.Security.KeyVault.Secrets;
33

4+
using GradeManagement.Data;
45
using GradeManagement.Shared.Dtos.GitHubManifest;
56

67
using Microsoft.AspNetCore.Mvc;
@@ -38,7 +39,7 @@ await client.SetSecretAsync($"GitHubMonitorConfig--{gitHubApp.Owner.Login}--GitH
3839
await client.SetSecretAsync($"GitHubMonitorConfig--{gitHubApp.Owner.Login}--GitHubWebhookSecret",
3940
gitHubApp.WebhookSecret);
4041

41-
return Redirect(appUrl);
42+
return Redirect($"https://github.com/organizations/ahk-dev-org/settings/apps/{gitHubApp.Slug}/installations");
4243
}
4344

4445
public static string RemovePemFencing(string pem)

grade-management-new/GradeManagement.Server/GradeManagement.Server.http

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@GradeManagement.Server_HostAddress = http://localhost:5180
1+
@GradeManagement.Server_HostAddress = https://app.mm-home.eu
22

33
GET {{GradeManagement.Server_HostAddress}}/weatherforecast/
44
Accept: application/json

grade-management-new/GradeManagement.Server/Properties/launchSettings.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@
1414
"dotnetRunMessages": true,
1515
"launchBrowser": true,
1616
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
17-
"applicationUrl": "http://10.0.0.176:5180",
17+
"applicationUrl": "http://10.0.0.10:5180",
1818
"environmentVariables": {
1919
"ASPNETCORE_ENVIRONMENT": "Development",
2020
"MONITOR_URL": "https://monitor.mm-home.eu/api/github-webhook",
2121
"KEY_VAULT_URI": "https://ahkgithubmonitorsecrets.vault.azure.net/",
22-
"APP_URL": "app.mm-home.eu"
22+
"APP_URL": "https://app.mm-home.eu/"
2323
}
2424
},
2525
"https": {
2626
"commandName": "Project",
2727
"dotnetRunMessages": true,
2828
"launchBrowser": false,
2929
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
30-
"applicationUrl": "https://10.0.0.176:7136;http://10.0.0.176:5180",
30+
"applicationUrl": "https://10.0.0.10:7136;http://10.0.0.10:5180",
3131
"environmentVariables": {
3232
"ASPNETCORE_ENVIRONMENT": "Development",
3333
"MONITOR_URL": "https://monitor.mm-home.eu/api/github-webhook",
3434
"KEY_VAULT_URI": "https://ahkgithubmonitorsecrets.vault.azure.net/",
35-
"APP_URL": "app.mm-home.eu"
35+
"APP_URL": "https://app.mm-home.eu/"
3636
}
3737
},
3838
"IIS Express": {

0 commit comments

Comments
 (0)