diff --git a/github-monitor/Ahk.GitHub.Monitor.Tests/IntegrationTests/Helpers/FunctionBuilder.cs b/github-monitor/Ahk.GitHub.Monitor.Tests/IntegrationTests/Helpers/FunctionBuilder.cs index ab6eb1e..b6560ec 100644 --- a/github-monitor/Ahk.GitHub.Monitor.Tests/IntegrationTests/Helpers/FunctionBuilder.cs +++ b/github-monitor/Ahk.GitHub.Monitor.Tests/IntegrationTests/Helpers/FunctionBuilder.cs @@ -1,5 +1,7 @@ +using System.Collections.Generic; using Ahk.GitHub.Monitor.Config; using Ahk.GitHub.Monitor.Services.EventDispatch; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; @@ -13,6 +15,21 @@ internal static class FunctionBuilder GitHubAppId = "appid", GitHubAppPrivateKey = "appprivatekey", GitHubWebhookSecret = "webhooksecret" }; + public static GitHubMonitorFunction Create(IEventDispatchService dispatchService = null) - => new(dispatchService ?? new Mock().Object, Options.Create(AppConfig), new Mock>().Object); + { + var configValues = new Dictionary + { + { "GitHubMonitorConfig:test:GitHubAppId", AppConfig.GitHubAppId }, + { "GitHubMonitorConfig:test:GitHubAppPrivateKey", AppConfig.GitHubAppPrivateKey }, + { "GitHubMonitorConfig:test:GitHubWebhookSecret", AppConfig.GitHubWebhookSecret } + }; + + var configuration = new ConfigurationBuilder() + .AddInMemoryCollection(configValues) + .Build(); + + return new GitHubMonitorFunction( + dispatchService ?? new Mock().Object, new Mock>().Object, configuration); + } } diff --git a/github-monitor/Ahk.GitHub.Monitor/GitHubMonitorFunction.cs b/github-monitor/Ahk.GitHub.Monitor/GitHubMonitorFunction.cs index a65cd33..f907003 100644 --- a/github-monitor/Ahk.GitHub.Monitor/GitHubMonitorFunction.cs +++ b/github-monitor/Ahk.GitHub.Monitor/GitHubMonitorFunction.cs @@ -6,6 +6,8 @@ using Ahk.GitHub.Monitor.EventHandlers.BaseAndUtils; using Ahk.GitHub.Monitor.Helpers; using Ahk.GitHub.Monitor.Services.EventDispatch; +using Azure.Identity; +using Azure.Security.KeyVault.Secrets; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.Functions.Worker; @@ -26,6 +28,13 @@ public async Task Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData request) { + string keyVaultUrl = Environment.GetEnvironmentVariable("KEY_VAULT_URI"); + if (keyVaultUrl == null) + { + return new BadRequestObjectResult(new { error = "Please set environment variable KEY_VAULT_URI" }); + } + var secretClient = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential()); + request.Headers.TryGetValues("X-GitHub-Event", out IEnumerable eventNameValues); var eventName = eventNameValues?.FirstOrDefault(); request.Headers.TryGetValues("X-GitHub-Delivery", out IEnumerable deliveryIdValues); @@ -42,6 +51,11 @@ public async Task Run( return new BadRequestObjectResult(new { error = "X-GitHub-Event header missing" }); } + if (eventName == "ping") + { + return new OkObjectResult("pong"); + } + if (string.IsNullOrEmpty(receivedSignature)) { return new BadRequestObjectResult(new { error = "X-Hub-Signature-256 header missing" }); @@ -56,10 +70,12 @@ public async Task Run( var orgName = parsedRequestBody.Repository.Owner.Login; - var orgConfig = new GitHubMonitorConfig(); - configuration.GetSection(GitHubMonitorConfig.GetSectionName(orgName)).Bind(orgConfig); + var githubAppId = await secretClient.GetSecretAsync($"GitHubMonitorConfig--{orgName}--GitHubAppId"); + var githubAppPrivateKey = await secretClient.GetSecretAsync($"GitHubMonitorConfig--{orgName}--GitHubAppPrivateKey"); + var githubWebhookSecret = await secretClient.GetSecretAsync($"GitHubMonitorConfig--{orgName}--GitHubWebhookSecret"); + - if (string.IsNullOrEmpty(orgConfig.GitHubWebhookSecret)) + if (string.IsNullOrEmpty(githubWebhookSecret.Value.Value)) { return new ObjectResult(new { error = "GitHub secret not configured" }) { @@ -67,8 +83,8 @@ public async Task Run( }; } - if (string.IsNullOrEmpty(orgConfig.GitHubAppId) || - string.IsNullOrEmpty(orgConfig.GitHubAppPrivateKey)) + if (string.IsNullOrEmpty(githubAppId.Value.Value) || + string.IsNullOrEmpty(githubAppPrivateKey.Value.Value)) { return new ObjectResult(new { error = "GitHub App ID/Token not configured" }) { @@ -77,7 +93,7 @@ public async Task Run( } if (!GitHubSignatureValidator.IsSignatureValid(requestBody, receivedSignature, - orgConfig.GitHubWebhookSecret)) + githubWebhookSecret.Value.Value)) { return new BadRequestObjectResult(new { error = "Payload signature not valid" }); } diff --git a/grade-management-new/GradeManagement.Bll/GradeManagement.Bll.csproj b/grade-management-new/GradeManagement.Bll/GradeManagement.Bll.csproj index 26e24c8..5b0c22d 100644 --- a/grade-management-new/GradeManagement.Bll/GradeManagement.Bll.csproj +++ b/grade-management-new/GradeManagement.Bll/GradeManagement.Bll.csproj @@ -14,6 +14,21 @@ + + + + + + + + + + + ..\..\..\..\.dotnet\shared\Microsoft.AspNetCore.App\8.0.11\Microsoft.AspNetCore.Http.Features.dll + + + ..\..\..\..\.dotnet\shared\Microsoft.AspNetCore.App\8.0.11\Microsoft.Extensions.Configuration.Binder.dll + diff --git a/grade-management-new/GradeManagement.Bll/Profiles/AutoMapperProfile.cs b/grade-management-new/GradeManagement.Bll/Profiles/AutoMapperProfile.cs index 211a59a..e4e6d38 100644 --- a/grade-management-new/GradeManagement.Bll/Profiles/AutoMapperProfile.cs +++ b/grade-management-new/GradeManagement.Bll/Profiles/AutoMapperProfile.cs @@ -2,6 +2,7 @@ using GradeManagement.Data.Models; using GradeManagement.Shared.Dtos; +using GradeManagement.Shared.Dtos.Request; using GradeManagement.Shared.Dtos.Response; using Assignment = GradeManagement.Data.Models.Assignment; @@ -21,7 +22,7 @@ public class AutoMapperProfile : Profile public AutoMapperProfile() { CreateMap(); - CreateMap(); + CreateMap(); CreateMap().ForMember(dest => dest.ScoreTypes, opt => opt.MapFrom(src => src.ScoreTypeExercises.Where(ste => ste.ExerciseId == src.Id) diff --git a/grade-management-new/GradeManagement.Bll/ServiceCollectionExtensions.cs b/grade-management-new/GradeManagement.Bll/ServiceCollectionExtensions.cs index 160f8b5..c587f08 100644 --- a/grade-management-new/GradeManagement.Bll/ServiceCollectionExtensions.cs +++ b/grade-management-new/GradeManagement.Bll/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ using GradeManagement.Bll.Services; +using GradeManagement.Bll.Services.Moodle; using Microsoft.Extensions.DependencyInjection; @@ -24,6 +25,8 @@ public static IServiceCollection AddBllServices(this IServiceCollection services services.AddTransient(); services.AddTransient(); services.AddTransient(); + services.AddTransient(); + services.AddTransient(); return services; } diff --git a/grade-management-new/GradeManagement.Bll/Services/AssignmentEventProcessorService.cs b/grade-management-new/GradeManagement.Bll/Services/AssignmentEventProcessorService.cs index d121322..0506d2c 100644 --- a/grade-management-new/GradeManagement.Bll/Services/AssignmentEventProcessorService.cs +++ b/grade-management-new/GradeManagement.Bll/Services/AssignmentEventProcessorService.cs @@ -5,6 +5,7 @@ using GradeManagement.Shared.Dtos.AssignmentEvents; using GradeManagement.Shared.Enums; +using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using Assignment = GradeManagement.Shared.Dtos.Assignment; @@ -38,6 +39,20 @@ public async Task ConsumeAssignmentAcceptedEventAsync(AssignmentAccepted assignm await using var transaction = await gradeManagementDbContext.Database.BeginTransactionAsync(); try { + var existingAssignment = await gradeManagementDbContext.Assignment.Where( + a => a.GithubRepoUrl == assignmentAccepted.GitHubRepositoryUrl).FirstOrDefaultAsync(); + if (existingAssignment != null) + { + var assignmentLogForExistingAssingnment = new AssignmentLog() + { + EventType = EventType.AssignmentAccepted, + Description = $"Assignment for github repo url {assignmentAccepted.GitHubRepositoryUrl} already exists!", + AssignmentId = existingAssignment.Id + }; + await assignmentLogService.CreateAsync(assignmentLogForExistingAssingnment); + return; + } + var repositoryName = GetRepositoryNameFromUrl(assignmentAccepted.GitHubRepositoryUrl); var exercise = await exerciseService.GetExerciseModelByGitHubRepoNameWithoutQfAsync(repositoryName); var studentGitHubId = repositoryName.Remove(0, (exercise.GithubPrefix + "-").Length); @@ -93,12 +108,10 @@ public async Task ConsumePullRequestOpenedEventAsync(PullRequestOpened pullReque BranchName = pullRequestOpened.BranchName, AssignmentId = assignment.Id }; - pullRequestToCreate = await pullRequestService.CreateWithoutQfAsync(pullRequestToCreate, assignment.SubjectId); + await pullRequestService.CreateWithoutQfAsync(pullRequestToCreate, assignment.SubjectId); pullRequest = await pullRequestService.GetModelByUrlWithoutQfAsync(pullRequestOpened.PullRequestUrl); } - - var assignmentLog = new AssignmentLog() { EventType = EventType.PullRequestOpened, @@ -123,7 +136,8 @@ public async Task ConsumeCiEvaluationCompletedEventAsync(CiEvaluationCompleted c await using var transaction = await gradeManagementDbContext.Database.BeginTransactionAsync(); try { - var pullRequest = await pullRequestService.GetModelByUrlWithoutQfAsync(ciEvaluationCompleted.PullRequestUrl); + var pullRequest = + await pullRequestService.GetModelByUrlWithoutQfAsync(ciEvaluationCompleted.PullRequestUrl); var repositoryName = GetRepositoryNameFromUrl(ciEvaluationCompleted.GitHubRepositoryUrl); var exercise = await exerciseService.GetExerciseModelByGitHubRepoNameWithoutQfAsync(repositoryName); var studentGitHubId = repositoryName.Remove(0, (exercise.GithubPrefix + "-").Length); @@ -131,7 +145,7 @@ public async Task ConsumeCiEvaluationCompletedEventAsync(CiEvaluationCompleted c var assignment = await assignmentService.GetAssignmentModelByGitHubRepoNameWithoutQfAsync(repositoryName); var subject = await subjectService.GetModelByIdWithoutQfAsync(exercise.SubjectId); - if(ciEvaluationCompleted.CiApiKey != subject.CiApiKey) + if (ciEvaluationCompleted.CiApiKey != subject.CiApiKey) { throw new SecurityTokenException("Invalid API key"); } @@ -149,7 +163,8 @@ public async Task ConsumeCiEvaluationCompletedEventAsync(CiEvaluationCompleted c foreach (var scoreEvent in ciEvaluationCompleted.Scores) { - await scoreService.CreateScoreBasedOnOrderAsync(scoreEvent.Key, scoreEvent.Value, pullRequest.Id, pullRequest.SubjectId, exercise.Id); + await scoreService.CreateScoreBasedOnOrderAsync(scoreEvent.Key, scoreEvent.Value, pullRequest.Id, + pullRequest.SubjectId, exercise.Id); } var assignmentLog = new AssignmentLog() @@ -196,7 +211,7 @@ public async Task ConsumeTeacherAssignedEventAsync(TeacherAssigned teacherAssign pullRequest.TeacherId = null; // Unassign previous teacher await gradeManagementDbContext.SaveChangesAsync(); - if(teacherAssigned.TeacherGitHubIds == null || teacherAssigned.TeacherGitHubIds.Count == 0) + if (teacherAssigned.TeacherGitHubIds == null || teacherAssigned.TeacherGitHubIds.Count == 0) { await transaction.CommitAsync(); return; @@ -229,7 +244,6 @@ public async Task ConsumeTeacherAssignedEventAsync(TeacherAssigned teacherAssign await transaction.CommitAsync(); } - } catch { @@ -247,24 +261,24 @@ public async Task ConsumeAssignmentGradedByTeacherEventAsync(AssignmentGradedByT var assignment = await assignmentService.GetAssignmentModelByGitHubRepoNameWithoutQfAsync(repositoryName); var exercise = await exerciseService.GetExerciseModelByGitHubRepoNameWithoutQfAsync(repositoryName); var teacher = await userService.GetModelByGitHubIdAsync(assignmentGradedByTeacher.TeacherGitHubId); - var pullRequest = await pullRequestService.GetModelByUrlWithoutQfAsync(assignmentGradedByTeacher.PullRequestUrl); + var pullRequest = + await pullRequestService.GetModelByUrlWithoutQfAsync(assignmentGradedByTeacher.PullRequestUrl); if (assignmentGradedByTeacher.Scores.IsNullOrEmpty()) { - var latestScores = await pullRequestService.GetLatestUnapprovedScoreModelsWithoutQfByIdAsync(pullRequest.Id); + var latestScores = + await pullRequestService.GetLatestUnapprovedScoreModelsWithoutQfByIdAsync(pullRequest.Id); foreach (var scoreEntity in latestScores) { - scoreEntity.IsApproved = true; - scoreEntity.TeacherId = teacher.Id; + await scoreService.ApproveScoreAsync(scoreEntity.Id, teacher.Id); } - - await gradeManagementDbContext.SaveChangesAsync(); } else { foreach (var eventScore in assignmentGradedByTeacher.Scores) { - await scoreService.CreateOrApprovePointsFromTeacherInputWithoutQfAsync(eventScore.Key, eventScore.Value, pullRequest.Id, teacher.Id, pullRequest.SubjectId, exercise.Id); + await scoreService.CreateOrApprovePointsFromTeacherInputWithoutQfAsync(eventScore.Key, + eventScore.Value, pullRequest.Id, teacher.Id, pullRequest.SubjectId, exercise.Id); } } @@ -292,7 +306,8 @@ public async Task ConsumePullRequestStatusChangedEventAsync(PullRequestStatusCha await using var transaction = await gradeManagementDbContext.Database.BeginTransactionAsync(); try { - var pullRequest = await pullRequestService.GetModelByUrlWithoutQfAsync(pullRequestStatusChanged.PullRequestUrl); + var pullRequest = + await pullRequestService.GetModelByUrlWithoutQfAsync(pullRequestStatusChanged.PullRequestUrl); pullRequest.Status = pullRequestStatusChanged.pullRequestStatus; await gradeManagementDbContext.SaveChangesAsync(); diff --git a/grade-management-new/GradeManagement.Bll/Services/BaseServices/ICrudServiceBase.cs b/grade-management-new/GradeManagement.Bll/Services/BaseServices/ICrudServiceBase.cs index 4d215ee..59f30ed 100644 --- a/grade-management-new/GradeManagement.Bll/Services/BaseServices/ICrudServiceBase.cs +++ b/grade-management-new/GradeManagement.Bll/Services/BaseServices/ICrudServiceBase.cs @@ -2,7 +2,5 @@ public interface ICrudServiceBase : IRestrictedCrudServiceBase { - public Task UpdateAsync(long id, TDto requestDto); - } diff --git a/grade-management-new/GradeManagement.Bll/Services/BaseServices/ICrudServiceBaseTwoParams.cs b/grade-management-new/GradeManagement.Bll/Services/BaseServices/ICrudServiceBaseTwoParams.cs index 11c063e..a1c87a7 100644 --- a/grade-management-new/GradeManagement.Bll/Services/BaseServices/ICrudServiceBaseTwoParams.cs +++ b/grade-management-new/GradeManagement.Bll/Services/BaseServices/ICrudServiceBaseTwoParams.cs @@ -2,7 +2,5 @@ public interface ICrudServiceBase : IRestrictedCrudServiceBase { - public Task UpdateAsync(long id, TRequestDto requestDto); - } diff --git a/grade-management-new/GradeManagement.Bll/Services/CourseService.cs b/grade-management-new/GradeManagement.Bll/Services/CourseService.cs index 2179bd7..0ece6e3 100644 --- a/grade-management-new/GradeManagement.Bll/Services/CourseService.cs +++ b/grade-management-new/GradeManagement.Bll/Services/CourseService.cs @@ -4,9 +4,15 @@ using AutSoft.Common.Exceptions; using AutSoft.Linq.Queryable; +using Azure.Identity; +using Azure.Security.KeyVault.Secrets; + using GradeManagement.Bll.Services.BaseServices; +using GradeManagement.Bll.Services.Utils; using GradeManagement.Data; -using GradeManagement.Shared.Dtos; +using GradeManagement.Data.Models; +using GradeManagement.Shared.Config; +using GradeManagement.Shared.Dtos.Request; using GradeManagement.Shared.Dtos.Response; using GradeManagement.Shared.Exceptions; @@ -15,28 +21,28 @@ namespace GradeManagement.Bll.Services; public class CourseService(GradeManagementDbContext gradeManagementDbContext, IMapper mapper) - : ICrudServiceBase + : ICrudServiceBase { - public async Task> GetAllAsync() + public async Task> GetAllAsync() { return await gradeManagementDbContext.Course .Include(c => c.Semester) .Include(c => c.Language) - .ProjectTo(mapper.ConfigurationProvider) + .ProjectTo(mapper.ConfigurationProvider) .OrderBy(c => c.Id) .ToListAsync(); } - public async Task GetByIdAsync(long id) + public async Task GetByIdAsync(long id) { return await gradeManagementDbContext.Course .Include(c => c.Semester) .Include(c => c.Language) - .ProjectTo(mapper.ConfigurationProvider) + .ProjectTo(mapper.ConfigurationProvider) .SingleEntityAsync(c => c.Id == id, id); } - public async Task UpdateAsync(long id, Course requestDto) + public async Task UpdateAsync(long id, CourseRequest requestDto) { if (requestDto.Id != id) { @@ -47,7 +53,7 @@ public async Task UpdateAsync(long id, Course requestDto) var courseEntity = await gradeManagementDbContext.Course .SingleEntityAsync(c => c.Id == id, id); courseEntity.Name = requestDto.Name; - courseEntity.MoodleCourseId = requestDto.MoodleCourseId; + courseEntity.MoodleClientId = requestDto.MoodleClientId; courseEntity.SubjectId = requestDto.SubjectId; courseEntity.SemesterId = requestDto.Semester.Id; courseEntity.LanguageId = requestDto.Language.Id; @@ -57,24 +63,30 @@ public async Task UpdateAsync(long id, Course requestDto) return await GetByIdAsync(courseEntity.Id); } - public async Task CreateAsync(Course requestDto) + public async Task CreateAsync(CourseRequest requestDto) { if (requestDto.SubjectId != gradeManagementDbContext.SubjectIdValue) { throw new UnauthorizedException("Current subject does not match the subject of the course!"); } - var courseEntityToBeCreated = new Data.Models.Course + var keyGenerator = new RsaKeyGenerator(); + + var courseEntityToBeCreated = new Course { Id = requestDto.Id, Name = requestDto.Name, - MoodleCourseId = requestDto.MoodleCourseId, + MoodleClientId = requestDto.MoodleClientId, + PublicKey = keyGenerator.PublicKey, SubjectId = requestDto.SubjectId, SemesterId = requestDto.Semester.Id, LanguageId = requestDto.Language.Id, }; gradeManagementDbContext.Course.Add(courseEntityToBeCreated); await gradeManagementDbContext.SaveChangesAsync(); + + await SetSecret(requestDto.MoodleClientId, keyGenerator.PrivateKey); + return await GetByIdAsync(courseEntityToBeCreated.Id); } @@ -101,4 +113,13 @@ public async Task> GetAllGroupsByIdAsync(long id) .ProjectTo(mapper.ConfigurationProvider) .ToListAsync(); } + + private static async Task SetSecret(string moodleClientId, string privateKey) + { + var keyVaultUrl = Environment.GetEnvironmentVariable("KEY_VAULT_URI"); + if (string.IsNullOrEmpty(keyVaultUrl)) throw new ArgumentException("Key vault URL is null or empty!"); + var client = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential()); + + await client.SetSecretAsync($"{MoodleConfig.Name}--{moodleClientId}--MoodlePrivateKey", privateKey); + } } diff --git a/grade-management-new/GradeManagement.Bll/Services/ExerciseService.cs b/grade-management-new/GradeManagement.Bll/Services/ExerciseService.cs index fd93056..9a055f7 100644 --- a/grade-management-new/GradeManagement.Bll/Services/ExerciseService.cs +++ b/grade-management-new/GradeManagement.Bll/Services/ExerciseService.cs @@ -31,30 +31,36 @@ public class ExerciseService( { public async Task> GetAllAsync() { - return await gradeManagementDbContext.Exercise + var exercises = await gradeManagementDbContext.Exercise .Include(e => e.ScoreTypeExercises).ThenInclude(ste => ste.ScoreType) .ProjectTo(mapper.ConfigurationProvider) .ToListAsync(); + return exercises; } public async Task GetByIdAsync(long id) { - return await gradeManagementDbContext.Exercise - .Include(e => e.ScoreTypeExercises).ThenInclude(ste => ste.ScoreType) - .ProjectTo(mapper.ConfigurationProvider) + var exerciseEntity = await gradeManagementDbContext.Exercise + .Include(e => e.ScoreTypeExercises) + .ThenInclude(ste => ste.ScoreType) .SingleEntityAsync(e => e.Id == id, id); + + return mapper.Map(exerciseEntity); } public async Task CreateAsync(ExerciseRequest requestDto) { + Exercise exerciseEntity; await using var transaction = await gradeManagementDbContext.Database.BeginTransactionAsync(); try { - var exerciseEntity = new Exercise() + exerciseEntity = new Exercise() { Name = requestDto.Name, GithubPrefix = requestDto.GithubPrefix, - dueDate = requestDto.dueDate, + ClassroomUrl = requestDto.ClassroomUrl, + MoodleScoreNamePrefix = requestDto.MoodleScoreNamePrefix, + DueDate = requestDto.DueDate, CourseId = requestDto.CourseId, SubjectId = gradeManagementDbContext.SubjectIdValue }; @@ -63,16 +69,17 @@ public async Task CreateAsync(ExerciseRequest requestDto) exerciseEntity = await gradeManagementDbContext.Exercise .SingleEntityAsync(e => e.Id == exerciseEntity.Id, exerciseEntity.Id); exerciseEntity.ScoreTypeExercises = - await GetScoreTypeExercisesByTypeAndOrderAsync(requestDto.ScoreTypes, exerciseEntity.Id); + await GetScoreTypeExercisesByTypeAndOrdernAsync(requestDto.ScoreTypes, exerciseEntity.Id); await gradeManagementDbContext.SaveChangesAsync(); await transaction.CommitAsync(); - return await GetByIdAsync(exerciseEntity.Id); } catch { await transaction.RollbackAsync(); throw; } + + return await GetByIdAsync(exerciseEntity.Id); } public async Task UpdateAsync(long id, ExerciseRequest requestDto) @@ -88,9 +95,10 @@ public async Task UpdateAsync(long id, ExerciseRequest request exerciseEntity.Name = requestDto.Name; exerciseEntity.GithubPrefix = requestDto.GithubPrefix; - exerciseEntity.dueDate = requestDto.dueDate; + exerciseEntity.DueDate = requestDto.DueDate; exerciseEntity.CourseId = requestDto.CourseId; - exerciseEntity.ScoreTypeExercises = await GetScoreTypeExercisesByTypeAndOrderAsync(requestDto.ScoreTypes, id); + exerciseEntity.ScoreTypeExercises = + await GetScoreTypeExercisesByTypeAndOrderInTransactionAsync(requestDto.ScoreTypes, id); await gradeManagementDbContext.SaveChangesAsync(); return await GetByIdAsync(exerciseEntity.Id); @@ -121,22 +129,13 @@ public async Task GetExerciseModelByGitHubRepoNameWithoutQfAsync(strin .SingleEntityAsync(e => githubRepoName.StartsWith(e.GithubPrefix), 0); } - private async Task> GetScoreTypeExercisesByTypeAndOrderAsync( + private async Task> GetScoreTypeExercisesByTypeAndOrderInTransactionAsync( Dictionary scoreTypes, long exerciseId) { await using var transaction = await gradeManagementDbContext.Database.BeginTransactionAsync(); try { - foreach (var (order, type) in scoreTypes) - { - var scoreType = await scoreTypeService.GetOrCreateScoreTypeByTypeStringAsync(type); - gradeManagementDbContext.ScoreTypeExercise.Add(new ScoreTypeExercise - { - ScoreTypeId = scoreType.Id, ExerciseId = exerciseId, Order = order - }); - } - - await gradeManagementDbContext.SaveChangesAsync(); + await GetScoreTypeExercisesByTypeAndOrdernAsync(scoreTypes, exerciseId); await transaction.CommitAsync(); } @@ -146,74 +145,32 @@ private async Task> GetScoreTypeExercisesByTypeAndOrderA throw; } - return gradeManagementDbContext.ScoreTypeExercise.Where(s => s.ExerciseId == exerciseId).ToList(); - } - - public async Task GetScoreTypeByOrderAndExerciseIdAsync(int order, long exerciseId) - { - var scoreTypeExercise = await gradeManagementDbContext.ScoreTypeExercise - .Include(ste => ste.ScoreType) - .SingleEntityAsync(ste => ste.ExerciseId == exerciseId && ste.Order == order, 0); - return scoreTypeExercise.ScoreType; + return await gradeManagementDbContext.ScoreTypeExercise.Where(s => s.ExerciseId == exerciseId).ToListAsync(); } - public async Task GetCsvByExerciseId(long exerciseId) + private async Task> GetScoreTypeExercisesByTypeAndOrdernAsync( + Dictionary scoreTypes, long exerciseId) { - var assignments = await gradeManagementDbContext.Assignment - .Where(a => a.ExerciseId == exerciseId) - .Include(assignment => assignment.Student) - .ToListAsync(); - - var records = new List>(); - - foreach (var assignment in assignments) + foreach (var (order, type) in scoreTypes) { - var pullRequest = await assignmentService.GetMergedPullRequestModelByIdAsync(assignment.Id); - if (pullRequest == null) - { - continue; - } - - var scores = await pullRequestService.GetApprovedScoreModelsByIdAsync(pullRequest.Id); - var record = new Dictionary + var scoreType = await scoreTypeService.GetOrCreateScoreTypeByTypeStringAsync(type); + gradeManagementDbContext.ScoreTypeExercise.Add(new ScoreTypeExercise { - { "NeptunCode", assignment.Student.NeptunCode }, { "SumOfScores", scores.Sum(s => s.Value) } - }; - foreach (var score in scores) - { - record[score.ScoreType.Type] = score.Value; - } - - - records.Add(record); - } - - await using var writer = new StringWriter(); - await using var csv = new CsvWriter(writer, CultureInfo.InvariantCulture); - - // Write the header - var keys = records[0].Keys; - foreach (var key in keys) - { - csv.WriteField(key); + ScoreTypeId = scoreType.Id, ExerciseId = exerciseId, Order = order + }); } - await csv.NextRecordAsync(); - - // Write the records - foreach (var record in records) - { - foreach (var value in record.Values) - { - csv.WriteField(value); - } - - await csv.NextRecordAsync(); - } + await gradeManagementDbContext.SaveChangesAsync(); - await csv.FlushAsync(); + return await gradeManagementDbContext.ScoreTypeExercise.Where(s => s.ExerciseId == exerciseId).ToListAsync(); + } - return writer.ToString(); + public async Task GetScoreTypeByOrderAndExerciseIdAsync(int order, long exerciseId) + { + var scoreTypeExercise = await gradeManagementDbContext.ScoreTypeExercise + .Include(ste => ste.ScoreType) + .SingleEntityAsync(ste => ste.ExerciseId == exerciseId && ste.Order == order, 0); + return scoreTypeExercise.ScoreType; } public async Task> GetScoreTypeExercisesByIdAsync(long id) @@ -225,4 +182,13 @@ public async Task GetCsvByExerciseId(long exerciseId) .ProjectTo(mapper.ConfigurationProvider) .ToListAsync(); } + + public async Task SetMoodleScoreUrlByClassroomUrlWithoutQueryFilterAsync(string clasroomUrl, string moodleScoreUrl) + { + var exercise = await gradeManagementDbContext.Exercise.IgnoreQueryFiltersButNotIsDeleted() + .SingleEntityAsync(e => e.ClassroomUrl == clasroomUrl, 0); + if (exercise.MoodleScoreUrl == moodleScoreUrl) return; + exercise.MoodleScoreUrl = moodleScoreUrl; + await gradeManagementDbContext.SaveChangesAsync(); + } } diff --git a/grade-management-new/GradeManagement.Bll/Services/Moodle/MoodleIntegrationService.cs b/grade-management-new/GradeManagement.Bll/Services/Moodle/MoodleIntegrationService.cs new file mode 100644 index 0000000..2db2a12 --- /dev/null +++ b/grade-management-new/GradeManagement.Bll/Services/Moodle/MoodleIntegrationService.cs @@ -0,0 +1,184 @@ +using GradeManagement.Data; +using GradeManagement.Data.Models; +using GradeManagement.Data.Utils; +using GradeManagement.Shared.Dtos.Moodle; +using GradeManagement.Shared.Exceptions; + +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; + +using System.IdentityModel.Tokens.Jwt; +using System.Net.Http.Headers; +using System.Text; + +using JsonSerializer = System.Text.Json.JsonSerializer; + +namespace GradeManagement.Bll.Services.Moodle; + +public class MoodleIntegrationService( + TokenGeneratorService tokenGeneratorService, + StudentService studentService, + ExerciseService exerciseService, + GradeManagementDbContext dbContext) +{ + private static Dictionary States { get; } = new(); + + public async Task UploadScore(Score score) + { + if (score.SyncedToMoodle || !score.IsApproved) return; + var exercise = score.PullRequest.Assignment.Exercise; + var course = exercise.Course; + var student = score.PullRequest.Assignment.Student; + var scoreType = score.ScoreType; + if (student.MoodleId == null) throw new MoodleSyncException("No moodle ID for student"); + + var token = await tokenGeneratorService.GenerateAccessToken(course); + + if (token == null) throw new MoodleSyncException("Token was null when trying to register score"); + var client = new HttpClient(); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + + var scoreToUpload = new LtiScore() + { + Timestamp = DateTimeOffset.Now.ToString("O"), + ScoreGiven = Convert.ToInt32(score.Value), + ScoreMaximum = 100, + UserId = student.MoodleId, + ActivityProgress = "Completed", + GradingProgress = "FullyGraded" + }; + + var label = exercise.MoodleScoreNamePrefix + scoreType.Type; + + var lineItem = GetOrCreateLineItemByLabel(label, token, exercise); + + var scoreUrl = string.Concat(lineItem.Id.AsSpan(0, lineItem.Id.LastIndexOf("?")), "/scores"); + + var scoreJson = JsonSerializer.Serialize(scoreToUpload); + var response = client.PostAsync( + scoreUrl, + new StringContent(scoreJson, Encoding.UTF8, + "application/vnd.ims.lis.v1.score+json")) + .GetAwaiter() + .GetResult(); + if (!response.IsSuccessStatusCode) + { + throw new MoodleSyncException("Score creation failed with status code: " + response.StatusCode + + " Reason phrase: " + response.ReasonPhrase); + } + + score.SyncedToMoodle = true; + await dbContext.SaveChangesAsync(); + } + + private static LtiLineItem GetOrCreateLineItemByLabel(string label, string token, Exercise exercise) + { + var lineItems = GetAllLineItems(token, exercise); + var lineItem = lineItems.FirstOrDefault(li => li.Label == label); + if (lineItem == null) + { + lineItem = CreateLineItem( + new LtiLineItemRequest() + { + StartDateTime = DateTime.Now, + EndDateTime = DateTime.Now.AddDays(10), + Label = label, + ScoreMaximum = 100 + }, token, exercise); + } + + return lineItem; + } + + private static List GetAllLineItems(string token, Exercise exercise) + { + var client = new HttpClient(); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + client.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/vnd.ims.lis.v2.lineitemcontainer+json")); + + var response = client.GetAsync(exercise.MoodleScoreUrl) + .GetAwaiter() + .GetResult(); + if (!response.IsSuccessStatusCode) + throw new MoodleSyncException("Line item request failed with status code: " + response.StatusCode); + return JsonSerializer.Deserialize>(response.Content.ReadAsStream()); + } + + private static LtiLineItem CreateLineItem(LtiLineItemRequest lineItem, string token, Exercise exercise) + { + var client = new HttpClient(); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); + client.DefaultRequestHeaders.Accept.Add( + new MediaTypeWithQualityHeaderValue("application/vnd.ims.lis.v2.lineitem+json")); + + var lineItemJSON = JsonSerializer.Serialize(lineItem); + var response = client.PostAsync( + exercise.MoodleScoreUrl, + new StringContent(lineItemJSON, Encoding.UTF8, + "application/vnd.ims.lis.v2.lineitem+json")) + .GetAwaiter() + .GetResult(); + if (!response.IsSuccessStatusCode) + throw new MoodleSyncException("Line item creation failed with status code: " + response.StatusCode); + return JsonSerializer.Deserialize(response.Content.ReadAsStream()); + } + + public string HandleOidc(IFormCollection formData) + { + var state = Guid.NewGuid().ToString(); + var nonce = Guid.NewGuid().ToString(); + States.Add(state, (formData["client_id"], nonce)); + + return "https://edu.vik.bme.hu/mod/lti/auth.php" + "?" + + "scope=openid&" + + "response_type=id_token&" + + "client_id=" + formData["client_id"] + "&" + + "redirect_uri=" + formData["target_link_uri"] + "&" + + "login_hint=" + formData["login_hint"] + "&" + + "state=" + state + "&" + + "response_mode=form_post&" + + "nonce=" + nonce + "&" + + "prompt=none&" + + "lti_message_hint=" + formData["lti_message_hint"]; + } + + public async Task HandleJWT(IFormCollection formData) + { + var state = States[formData["state"]]; + if (state == (null, null)) throw new MoodleSyncException("No state saved with given value!"); + States.Remove(formData["state"]); + var id_token = formData["id_token"].FirstOrDefault(); + if (id_token == null) throw new MoodleSyncException("No token available to be read!"); + var tokenHandler = new JwtSecurityTokenHandler(); + var token = tokenHandler.ReadToken(id_token) as JwtSecurityToken; + if (token == null) throw new MoodleSyncException("Error parsing token!"); + if (!token.Payload["aud"].Equals(state.Item1) || !token.Payload["nonce"].Equals(state.Item2)) + throw new MoodleSyncException("Wrong aud or nonce!"); + var lisClaimString = token.Payload[LtiLisClaim.JwtUrl].ToString() ?? + throw new MoodleSyncException("Lis claim is null"); + var lisClaim = JsonSerializer.Deserialize(lisClaimString); + var studentName = token.Payload["name"].ToString() ?? throw new MoodleSyncException("Student name is null"); + var studentMoodleId = token.Payload["sub"].ToString() ?? throw new MoodleSyncException("sub is null"); + await studentService.CreateStudentIfNotAvailableByNeptunAsync(lisClaim.PersonSourcedId, studentName, + studentMoodleId); + var ltiResourceLinkString = token.Payload[LtiResourceLink.JwtUrl].ToString() ?? + throw new MoodleSyncException("Resource link was null"); + var ltiResourceLink = JsonSerializer.Deserialize(ltiResourceLinkString); + var classroomUrl = ltiResourceLink.Description; + if (string.IsNullOrEmpty(classroomUrl) || !IsValidUrl(classroomUrl)) + throw new MoodleSyncException("Classroom URL was either null, empty or invalid!"); + var lineItemsString = token.Payload[LtiLineItemsWrapper.JwtUrl].ToString() ?? + throw new MoodleSyncException("Line item was null"); + var lineItems = JsonSerializer.Deserialize(lineItemsString); + await exerciseService.SetMoodleScoreUrlByClassroomUrlWithoutQueryFilterAsync(classroomUrl, lineItems.LineItems); + + return classroomUrl; + } + + public static bool IsValidUrl(string url) + { + return Uri.IsWellFormedUriString(url, UriKind.Absolute) && + (url.StartsWith("http://") || url.StartsWith("https://")); + } +} diff --git a/grade-management-new/GradeManagement.Bll/Services/Moodle/TokenGeneratorService.cs b/grade-management-new/GradeManagement.Bll/Services/Moodle/TokenGeneratorService.cs new file mode 100644 index 0000000..d7ac9a9 --- /dev/null +++ b/grade-management-new/GradeManagement.Bll/Services/Moodle/TokenGeneratorService.cs @@ -0,0 +1,111 @@ +using Azure.Identity; +using Azure.Security.KeyVault.Secrets; + +using GradeManagement.Data.Models; +using GradeManagement.Shared.Config; +using GradeManagement.Shared.Exceptions; + +using Jose; + +using Microsoft.Extensions.Configuration; + +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Parameters; +using Org.BouncyCastle.OpenSsl; +using Org.BouncyCastle.Security; + +using System.Net.Http.Json; +using System.Security.Claims; +using System.Security.Cryptography; + +namespace GradeManagement.Bll.Services.Moodle; + +public class TokenGeneratorService(IConfiguration configuration) +{ + private const string Scope = + "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"; + + public async Task GenerateAccessToken(Course course) + { + var token = await MakeClientAssertionToken(course); + + var endPoint = "https://edu.vik.bme.hu/mod/lti/token.php"; + var client = new HttpClient(); + + var data = new[] + { + new KeyValuePair("grant_type", "client_credentials"), new KeyValuePair( + "client_assertion_type", + "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"), + new KeyValuePair("client_assertion", token), + new KeyValuePair("scope", Scope), + }; + var result = client.PostAsync(endPoint, new FormUrlEncodedContent(data)).GetAwaiter().GetResult(); + var content = result.Content.ReadFromJsonAsync().Result; + + return content?.Access_token; + } + + private async Task MakeClientAssertionToken(Course course) + { + var appUrl = configuration["APP_URL"]; + if (string.IsNullOrEmpty(appUrl)) throw new MoodleSyncException("App url was null or empty!"); + + var claims = new List(); + claims.Add(new Claim("iss", appUrl)); + claims.Add(new Claim("iat", ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds).ToString())); + claims.Add(new Claim("exp", + ((int)(DateTime.UtcNow.AddHours(1) - new DateTime(1970, 1, 1)).TotalSeconds).ToString())); + claims.Add(new Claim("aud", "https://edu.vik.bme.hu/mod/lti/token.php")); + claims.Add(new Claim("sub", course.MoodleClientId)); + + return await CreateToken(claims, course); + } + + private async Task CreateToken(List claims, Course course) + { + string keyVaultUrl = Environment.GetEnvironmentVariable("KEY_VAULT_URI"); + if (keyVaultUrl == null) + { + throw new Exception("Please set environment variable KEY_VAULT_URI"); + } + + var secretClient = new SecretClient(new Uri(keyVaultUrl), new DefaultAzureCredential()); + var moodlePrivateKey = + await secretClient.GetSecretAsync($"{MoodleConfig.Name}--{course.MoodleClientId}--MoodlePrivateKey"); + + var privateRsaKey = moodlePrivateKey.Value.Value; + if (string.IsNullOrEmpty(privateRsaKey)) throw new MoodleSyncException("Private RSA was null or empty!"); + + privateRsaKey = privateRsaKey.Trim(); + + RSAParameters rsaParams; + using (var tr = new StringReader(privateRsaKey)) + { + var pemReader = new PemReader(tr); + var keyPair = pemReader.ReadObject() as AsymmetricCipherKeyPair; + if (keyPair == null) + { + throw new MoodleSyncException("Could not read RSA private key"); + } + + var privateRsaParams = keyPair.Private as RsaPrivateCrtKeyParameters; + rsaParams = DotNetUtilities.ToRSAParameters(privateRsaParams); + } + + using (var rsa = new RSACryptoServiceProvider()) + { + rsa.ImportParameters(rsaParams); + var payload = claims.ToDictionary(k => k.Type, v => (object)v.Value); + return JWT.Encode(payload, rsa, JwsAlgorithm.RS256); + } + } + + private class PlatformTokenResponse + { + public string Access_token { get; set; } + public string Token_type { get; set; } + public int Expires_in { get; set; } + public string Scope { get; set; } + } +} diff --git a/grade-management-new/GradeManagement.Bll/Services/PullRequestService.cs b/grade-management-new/GradeManagement.Bll/Services/PullRequestService.cs index 036736d..d153176 100644 --- a/grade-management-new/GradeManagement.Bll/Services/PullRequestService.cs +++ b/grade-management-new/GradeManagement.Bll/Services/PullRequestService.cs @@ -62,17 +62,9 @@ public async Task> GetAllScoresByIdSortedByDateDescendingAsyn return await gradeManagementDbContext.Score .IgnoreQueryFiltersButNotIsDeleted() .Where(s => s.PullRequestId == id && !s.IsApproved) - .Include(s=>s.ScoreType) + .Include(s => s.ScoreType) .GroupBy(s => s.ScoreType) .Select(g => g.OrderByDescending(s => s.CreatedDate).FirstOrDefault()) .ToListAsync(); } - - public async Task> GetApprovedScoreModelsByIdAsync(long id) - { - return await gradeManagementDbContext.Score - .Where(s => s.PullRequestId == id && s.IsApproved) - .Include(s => s.ScoreType) - .ToListAsync(); - } } diff --git a/grade-management-new/GradeManagement.Bll/Services/ScoreService.cs b/grade-management-new/GradeManagement.Bll/Services/ScoreService.cs index 8deec49..c6f402f 100644 --- a/grade-management-new/GradeManagement.Bll/Services/ScoreService.cs +++ b/grade-management-new/GradeManagement.Bll/Services/ScoreService.cs @@ -1,4 +1,7 @@ -using GradeManagement.Data; +using AutSoft.Linq.Queryable; + +using GradeManagement.Bll.Services.Moodle; +using GradeManagement.Data; using GradeManagement.Data.Models; using GradeManagement.Data.Utils; using GradeManagement.Shared.Dtos.AssignmentEvents; @@ -7,9 +10,13 @@ namespace GradeManagement.Bll.Services; -public class ScoreService(GradeManagementDbContext gradeManagementDbContext, ScoreTypeService scoreTypeService, ExerciseService exerciseService) +public class ScoreService( + GradeManagementDbContext gradeManagementDbContext, + MoodleIntegrationService moodleIntegrationService, + ExerciseService exerciseService) { - public async Task CreateScoreBasedOnOrderAsync(int order, double score, long pullRequestId, long subjectId, long exerciseId) + public async Task CreateScoreBasedOnOrderAsync(int order, double score, long pullRequestId, long subjectId, + long exerciseId) { var scoreEntity = new Score { @@ -24,6 +31,24 @@ public async Task CreateScoreBasedOnOrderAsync(int order, double score, long pul await gradeManagementDbContext.SaveChangesAsync(); } + public async Task ApproveScoreAsync(long scoreId, long teacherId) + { + var score = await gradeManagementDbContext.Score + .IgnoreQueryFiltersButNotIsDeleted() + .Include(s => s.PullRequest) + .ThenInclude(pr => pr.Assignment).ThenInclude(a => a.Exercise).ThenInclude(e => e.Course) + .Include(s => s.PullRequest) + .ThenInclude(pr => pr.Assignment).ThenInclude(a => a.Student) + .Include(s => s.ScoreType) + .SingleEntityAsync(s => s.Id == scoreId, scoreId); + + score.IsApproved = true; + score.TeacherId = teacherId; + + gradeManagementDbContext.SaveChangesAsync(); + moodleIntegrationService.UploadScore(score); + } + public async Task CreateOrApprovePointsFromTeacherInputWithoutQfAsync( int order, double score, long pullRequestId, long teacherId, long subjectId, long exerciseId) { @@ -51,6 +76,17 @@ public async Task CreateOrApprovePointsFromTeacherInputWithoutQfAsync( await gradeManagementDbContext.SaveChangesAsync(); + + var scoreToUpload = await gradeManagementDbContext.Score + .IgnoreQueryFiltersButNotIsDeleted() + .Include(s => s.PullRequest) + .ThenInclude(pr => pr.Assignment).ThenInclude(a => a.Exercise).ThenInclude(e => e.Course) + .Include(s => s.PullRequest) + .ThenInclude(pr => pr.Assignment).ThenInclude(a => a.Student) + .Include(s => s.ScoreType) + .SingleEntityAsync(s => s.Id == scoreEntity.Id, scoreEntity.Id); + + moodleIntegrationService.UploadScore(scoreToUpload); } private async Task GetLatestModelByScoreValueAndTypeWithoutQfAsync(double score, ScoreType scoreType) diff --git a/grade-management-new/GradeManagement.Bll/Services/StudentService.cs b/grade-management-new/GradeManagement.Bll/Services/StudentService.cs index ec974bb..a7fb637 100644 --- a/grade-management-new/GradeManagement.Bll/Services/StudentService.cs +++ b/grade-management-new/GradeManagement.Bll/Services/StudentService.cs @@ -132,6 +132,18 @@ public async Task GetOrCreateStudentByGitHubIdAsync(string studentGitHu return student; } + public async Task CreateStudentIfNotAvailableByNeptunAsync(string studentNeptun, string studentName, string studentMoodleId) + { + var student = await gradeManagementDbContext.Student + .SingleOrDefaultAsync(s => s.NeptunCode == studentNeptun); + + if (student != null) return; + + student = new Student { Name = studentName, NeptunCode = studentNeptun, MoodleId = studentMoodleId}; + gradeManagementDbContext.Student.Add(student); + await gradeManagementDbContext.SaveChangesAsync(); + } + public async Task GetStudentModelByGitHubIdAsync(string studentGitHubId) { return await gradeManagementDbContext.Student.SingleEntityAsync(s => s.GithubId == studentGitHubId, 0); diff --git a/grade-management-new/GradeManagement.Bll/Services/SubjectService.cs b/grade-management-new/GradeManagement.Bll/Services/SubjectService.cs index eb43c5d..d3aaafc 100644 --- a/grade-management-new/GradeManagement.Bll/Services/SubjectService.cs +++ b/grade-management-new/GradeManagement.Bll/Services/SubjectService.cs @@ -16,7 +16,6 @@ using System.Security.Claims; -using Course = GradeManagement.Shared.Dtos.Course; using Task = System.Threading.Tasks.Task; using User = GradeManagement.Shared.Dtos.User; @@ -164,13 +163,13 @@ public async Task DeleteAsync(long id) await gradeManagementDbContext.SaveChangesAsync(); } - public async Task> GetAllCoursesByIdAsync(long id) + public async Task> GetAllCoursesByIdAsync(long id) { return await gradeManagementDbContext.Course .Include(c => c.Semester) .Include(c => c.Language) .Where(c => c.SubjectId == id) - .ProjectTo(mapper.ConfigurationProvider) + .ProjectTo(mapper.ConfigurationProvider) .ToListAsync(); } diff --git a/grade-management-new/GradeManagement.Bll/Services/Utils/RsaKeyGenerator.cs b/grade-management-new/GradeManagement.Bll/Services/Utils/RsaKeyGenerator.cs new file mode 100644 index 0000000..799b03c --- /dev/null +++ b/grade-management-new/GradeManagement.Bll/Services/Utils/RsaKeyGenerator.cs @@ -0,0 +1,47 @@ +namespace GradeManagement.Bll.Services.Utils; + +using System.Security.Cryptography; +using System.Text; + +public class RsaKeyGenerator +{ + public string PrivateKey { get; private set; } + public string PublicKey { get; private set; } + + public RsaKeyGenerator() + { + using var rsa = RSA.Create(2048); + + PrivateKey = ExportPrivateKey(rsa); + PublicKey = ExportPublicKey(rsa); + } + + private string ExportPrivateKey(RSA rsa) + { + var privateKeyBytes = rsa.ExportRSAPrivateKey(); + var base64PrivateKey = Convert.ToBase64String(privateKeyBytes); + var sb = new StringBuilder(); + sb.AppendLine("-----BEGIN RSA PRIVATE KEY-----"); + for (int i = 0; i < base64PrivateKey.Length; i += 64) + { + sb.AppendLine(base64PrivateKey.Substring(i, Math.Min(64, base64PrivateKey.Length - i))); + } + + sb.AppendLine("-----END RSA PRIVATE KEY-----"); + return sb.ToString(); + } + + private string ExportPublicKey(RSA rsa) + { + var publicKeyBytes = rsa.ExportSubjectPublicKeyInfo(); + var base64PublicKey = Convert.ToBase64String(publicKeyBytes); + var sb = new StringBuilder(); + sb.AppendLine("-----BEGIN PUBLIC KEY-----"); + for (int i = 0; i < base64PublicKey.Length; i += 64) + { + sb.AppendLine(base64PublicKey.Substring(i, Math.Min(64, base64PublicKey.Length - i))); + } + sb.AppendLine("-----END PUBLIC KEY-----"); + return sb.ToString(); + } +} diff --git a/grade-management-new/GradeManagement.Client/Components/ExerciseDataGrid.razor b/grade-management-new/GradeManagement.Client/Components/ExerciseDataGrid.razor index a9bf42c..7dd91ad 100644 --- a/grade-management-new/GradeManagement.Client/Components/ExerciseDataGrid.razor +++ b/grade-management-new/GradeManagement.Client/Components/ExerciseDataGrid.razor @@ -1,38 +1,77 @@ -@inject ExerciseClient ExerciseClient +@using GradeManagement.Client.Components.NewDialogs +@inject IDialogService DialogService +@inject ExerciseClient ExerciseClient - + - + + + - + + + + + + - + @code { [Parameter] public ICollection Values { get; set; } - private string JoinScoreTypes(ExerciseResponse item) => string.Join(", ", item.ScoreTypes.Select(x => $"{x.Key}: {x.Value}")); + private string JoinScoreTypes(ExerciseResponse item) => + string.Join(", ", item.ScoreTypes.Select(x => $"{x.Key}: {x.Value}")); - private async Task StartEditing(CellContext context) + private async Task EditExercise(CellContext context) { - await context.Actions.StartEditingItemAsync(); - StateHasChanged(); - } + var item = context.Item; + if (item == null) return; - private async Task CommittedItemChanges(ExerciseResponse items) - { - await ExerciseClient.UpdateAsync(items.Id, items.ToRequest()); + var parameters = new DialogParameters + { + ["value"] = item.ToRequest() + }; + + var dialog = DialogService.Show("Edit Exercise", parameters); + var result = await dialog.Result; + + if (!result.Canceled && result.Data is ExerciseRequest updated) + { + var updatedResponse = await ExerciseClient.UpdateAsync(item.Id, updated); + + var index = Values.ToList().FindIndex(x => x.Id == item.Id); + if (Values is List list && index >= 0 && index < list.Count) + { + list[index] = updatedResponse; + } + + StateHasChanged(); + } } - private async Task DeleteItem(ExerciseResponse item) + private async Task DeleteExercise(CellContext context) { - Values.Remove(item); - await ExerciseClient.DeleteAsync(item.Id); - StateHasChanged(); + var item = context.Item; + if (item == null) return; + + var confirm = await DialogService.ShowMessageBox( + "Delete Confirmation", + $"Delete '{item.Name}'?", + yesText: "Yes", cancelText: "No"); + + if (confirm is true) + { + Values.Remove(item); + await ExerciseClient.DeleteAsync(item.Id); + StateHasChanged(); + } } } diff --git a/grade-management-new/GradeManagement.Client/Components/Helpers/SubjectExtension.cs b/grade-management-new/GradeManagement.Client/Components/Helpers/SubjectExtension.cs index 56ec45a..1374d7e 100644 --- a/grade-management-new/GradeManagement.Client/Components/Helpers/SubjectExtension.cs +++ b/grade-management-new/GradeManagement.Client/Components/Helpers/SubjectExtension.cs @@ -46,7 +46,9 @@ public static ExerciseRequest ToRequest(this ExerciseResponse exercise) Name = exercise.Name, DueDate = exercise.DueDate, GithubPrefix = exercise.GithubPrefix, - ScoreTypes = exercise.ScoreTypes + ScoreTypes = exercise.ScoreTypes, + ClassroomUrl = exercise.ClassroomUrl, + MoodleScoreNamePrefix = exercise.MoodleScoreNamePrefix }; } diff --git a/grade-management-new/GradeManagement.Client/Components/NewDialogs/NewCourseDialog.razor b/grade-management-new/GradeManagement.Client/Components/NewDialogs/NewCourseDialog.razor index f19309e..498a0b4 100644 --- a/grade-management-new/GradeManagement.Client/Components/NewDialogs/NewCourseDialog.razor +++ b/grade-management-new/GradeManagement.Client/Components/NewDialogs/NewCourseDialog.razor @@ -1,11 +1,13 @@ - + New Course - - + + @@ -23,7 +25,7 @@ private bool success; private string[] errors; - [Parameter] public Course Value { get; set; } = new Course(); + [Parameter] public CourseRequest Value { get; set; } = new CourseRequest(); void Submit() => MudDialog.Close(DialogResult.Ok(Value)); void Cancel() => MudDialog.Cancel(); diff --git a/grade-management-new/GradeManagement.Client/Components/NewDialogs/NewExerciseDialog.razor b/grade-management-new/GradeManagement.Client/Components/NewDialogs/NewExerciseDialog.razor index 78f3a2a..7b93ff7 100644 --- a/grade-management-new/GradeManagement.Client/Components/NewDialogs/NewExerciseDialog.razor +++ b/grade-management-new/GradeManagement.Client/Components/NewDialogs/NewExerciseDialog.razor @@ -3,12 +3,39 @@ New Exercise - - - - @* *@ - @* *@ + + + + + + + + Score Types + + @foreach (var item in OrderedScoreTypes.Select((kvp, index) => new { kvp.Key, kvp.Value, index })) + { + + + + + + + } + + + + Add Score Type + + Cancel @@ -23,7 +50,14 @@ private bool success; private string[] errors; - private void Submit() => MudDialog.Close(DialogResult.Ok(value)); + [Parameter] + public ExerciseRequest Value { get; set; } = new() + { + DueDate = DateTime.Now, + ScoreTypes = new Dictionary() + }; + + private void Submit() => MudDialog.Close(DialogResult.Ok(Value)); private void Cancel() => MudDialog.Cancel(); async void OnSubmitClicked() @@ -35,10 +69,54 @@ } } - public ExerciseRequest value = new() + // ScoreTypes Logic + private List> OrderedScoreTypes => + Value.ScoreTypes.OrderBy(kvp => int.Parse(kvp.Key)).ToList(); + + private void AddScoreType() { - DueDate = DateTime.Now, - ScoreTypes = new Dictionary() - }; + int nextKey = Value.ScoreTypes.Count + 1; + Value.ScoreTypes[nextKey.ToString()] = ""; + } + + private void RemoveScoreType(int index) + { + var list = OrderedScoreTypes; + if (index < 0 || index >= list.Count) return; + + list.RemoveAt(index); + ReorderScoreTypes(list); + } + + private void MoveScoreTypeUp(int index) + { + if (index <= 0) return; + var list = OrderedScoreTypes; + (list[index - 1], list[index]) = (list[index], list[index - 1]); + ReorderScoreTypes(list); + } + + private void MoveScoreTypeDown(int index) + { + var list = OrderedScoreTypes; + if (index >= list.Count - 1) return; + (list[index + 1], list[index]) = (list[index], list[index + 1]); + ReorderScoreTypes(list); + } + + private void UpdateScoreType(int index, string newValue) + { + var list = OrderedScoreTypes; + var pair = list[index]; + list[index] = new KeyValuePair(pair.Key, newValue); + ReorderScoreTypes(list); + } + + private void ReorderScoreTypes(List> list) + { + Value.ScoreTypes = list + .Select((kvp, idx) => new KeyValuePair((idx + 1).ToString(), kvp.Value)) + .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); + } } diff --git a/grade-management-new/GradeManagement.Client/Layout/AppBar.razor b/grade-management-new/GradeManagement.Client/Layout/AppBar.razor index bcaa3c7..d430fbd 100644 --- a/grade-management-new/GradeManagement.Client/Layout/AppBar.razor +++ b/grade-management-new/GradeManagement.Client/Layout/AppBar.razor @@ -8,8 +8,8 @@ AHK Review UI + - @* *@ diff --git a/grade-management-new/GradeManagement.Client/Network/NetworkManager.cs b/grade-management-new/GradeManagement.Client/Network/NetworkManager.cs index 4993502..bef3f22 100644 --- a/grade-management-new/GradeManagement.Client/Network/NetworkManager.cs +++ b/grade-management-new/GradeManagement.Client/Network/NetworkManager.cs @@ -1,6 +1,6 @@ //---------------------- // -// Generated using the NSwag toolchain v14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) +// Generated using the NSwag toolchain v14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0)) (http://NSwag.org) // //---------------------- @@ -8,30 +8,40 @@ #pragma warning disable 114 // Disable "CS0114 '{derivedDto}.RaisePropertyChanged(String)' hides inherited member 'dtoBase.RaisePropertyChanged(String)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword." #pragma warning disable 472 // Disable "CS0472 The result of the expression is always 'false' since a value of type 'Int32' is never equal to 'null' of type 'Int32?' #pragma warning disable 612 // Disable "CS0612 '...' is obsolete" +#pragma warning disable 649 // Disable "CS0649 Field is never assigned to, and will always have its default value null" #pragma warning disable 1573 // Disable "CS1573 Parameter '...' has no matching param tag in the XML comment for ... #pragma warning disable 1591 // Disable "CS1591 Missing XML comment for publicly visible type or member ..." #pragma warning disable 8073 // Disable "CS8073 The result of the expression is always 'false' since a value of type 'T' is never equal to 'null' of type 'T?'" #pragma warning disable 3016 // Disable "CS3016 Arrays as attribute arguments is not CLS-compliant" +#pragma warning disable 8600 // Disable "CS8600 Converting null literal or possible null value to non-nullable type" +#pragma warning disable 8602 // Disable "CS8602 Dereference of a possibly null reference" #pragma warning disable 8603 // Disable "CS8603 Possible null reference return" #pragma warning disable 8604 // Disable "CS8604 Possible null reference argument for parameter" #pragma warning disable 8625 // Disable "CS8625 Cannot convert null literal to non-nullable reference type" -#pragma warning disable CS8765 // Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes). +#pragma warning disable 8765 // Disable "CS8765 Nullability of type of parameter doesn't match overridden member (possibly because of nullability attributes)." namespace GradeManagement.Client.Network { using System = global::System; - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AssignmentClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public AssignmentClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -41,10 +51,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -69,7 +92,7 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/assignments" urlBuilder_.Append("api/assignments"); @@ -148,7 +171,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(long i request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/assignments/{id}" urlBuilder_.Append("api/assignments/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -228,7 +251,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(long i request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/assignments/{id}/pullrequests" urlBuilder_.Append("api/assignments/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -398,17 +421,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AssingmentEventTestClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public AssingmentEventTestClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -418,10 +448,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -445,14 +488,14 @@ public virtual async System.Threading.Tasks.Task AssignmentAcceptedAsync(Assignm { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(assignmentAccepted, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(assignmentAccepted, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/testassignmentevents/assignmentaccepted" urlBuilder_.Append("api/testassignmentevents/assignmentaccepted"); @@ -522,14 +565,14 @@ public virtual async System.Threading.Tasks.Task PullRequestOpenedAsync(PullRequ { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(pullRequestOpened, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(pullRequestOpened, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/testassignmentevents/pullrequestopened" urlBuilder_.Append("api/testassignmentevents/pullrequestopened"); @@ -599,14 +642,14 @@ public virtual async System.Threading.Tasks.Task CiEvaluationCompletedAsync(CiEv { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(ciEvaluationCompleted, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(ciEvaluationCompleted, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/testassignmentevents/cievaluationcompleted" urlBuilder_.Append("api/testassignmentevents/cievaluationcompleted"); @@ -676,14 +719,14 @@ public virtual async System.Threading.Tasks.Task TeacherAssignedAsync(TeacherAss { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(teacherAssigned, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(teacherAssigned, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/testassignmentevents/teacherassigned" urlBuilder_.Append("api/testassignmentevents/teacherassigned"); @@ -753,14 +796,14 @@ public virtual async System.Threading.Tasks.Task AssignmentGradedAsync(Assignmen { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(assignmentGraded, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(assignmentGraded, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/testassignmentevents/assignmentgraded" urlBuilder_.Append("api/testassignmentevents/assignmentgraded"); @@ -830,14 +873,14 @@ public virtual async System.Threading.Tasks.Task PullRequestClosedAsync(PullRequ { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(pullRequestStatusChanged, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(pullRequestStatusChanged, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/testassignmentevents/pullrequestclosed" urlBuilder_.Append("api/testassignmentevents/pullrequestclosed"); @@ -1000,17 +1043,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class CiEvaluationClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public CiEvaluationClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -1020,10 +1070,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -1047,14 +1110,14 @@ public virtual async System.Threading.Tasks.Task CiEvaluationCompletedAsync(CiEv { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(ciEvaluationCompleted, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(ciEvaluationCompleted, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; request_.Method = new System.Net.Http.HttpMethod("POST"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/cievaluation/completed" urlBuilder_.Append("api/cievaluation/completed"); @@ -1217,17 +1280,264 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class ConfigClient + { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + + private System.Net.Http.HttpClient _httpClient; + private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; + + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public ConfigClient(System.Net.Http.HttpClient httpClient) + #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + BaseUrl = "http://localhost:5180"; + _httpClient = httpClient; + Initialize(); + } + + private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() + { + var settings = new Newtonsoft.Json.JsonSerializerSettings(); + UpdateJsonSerializerSettings(settings); + return settings; + } + + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } + + static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + + partial void Initialize(); + + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); + partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); + + /// A server side error occurred. + public virtual System.Threading.Tasks.Task GetAppUrlAsync() + { + return GetAppUrlAsync(System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task GetAppUrlAsync(System.Threading.CancellationToken cancellationToken) + { + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + + var urlBuilder_ = new System.Text.StringBuilder(); + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); + // Operation Path: "api/config/app-url" + urlBuilder_.Append("api/config/app-url"); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = new System.Collections.Generic.Dictionary>(); + foreach (var item_ in response_.Headers) + headers_[item_.Key] = item_.Value; + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + return; + } + else + if (status_ == 404) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + throw new ApiException("A server side error occurred.", status_, objectResponse_.Text, headers_, objectResponse_.Object, null); + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + protected struct ObjectResponseResult + { + public ObjectResponseResult(T responseObject, string responseText) + { + this.Object = responseObject; + this.Text = responseText; + } + + public T Object { get; } + + public string Text { get; } + } + + public bool ReadResponseAsString { get; set; } + + protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Threading.CancellationToken cancellationToken) + { + if (response == null || response.Content == null) + { + return new ObjectResponseResult(default(T), string.Empty); + } + + if (ReadResponseAsString) + { + var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject(responseText, JsonSerializerSettings); + return new ObjectResponseResult(typedBody, responseText); + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body string as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception); + } + } + else + { + try + { + using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + using (var streamReader = new System.IO.StreamReader(responseStream)) + using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader)) + { + var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings); + var typedBody = serializer.Deserialize(jsonTextReader); + return new ObjectResponseResult(typedBody, string.Empty); + } + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body stream as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception); + } + } + } + + private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo) + { + if (value == null) + { + return ""; + } + + if (value is System.Enum) + { + var name = System.Enum.GetName(value.GetType(), value); + if (name != null) + { + var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); + if (field != null) + { + var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) + as System.Runtime.Serialization.EnumMemberAttribute; + if (attribute != null) + { + return attribute.Value != null ? attribute.Value : name; + } + } + + var converted = System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo)); + return converted == null ? string.Empty : converted; + } + } + else if (value is bool) + { + return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant(); + } + else if (value is byte[]) + { + return System.Convert.ToBase64String((byte[]) value); + } + else if (value is string[]) + { + return string.Join(",", (string[])value); + } + else if (value.GetType().IsArray) + { + var valueArray = (System.Array)value; + var valueTextArray = new string[valueArray.Length]; + for (var i = 0; i < valueArray.Length; i++) + { + valueTextArray[i] = ConvertToString(valueArray.GetValue(i), cultureInfo); + } + return string.Join(",", valueTextArray); + } + + var result = System.Convert.ToString(value, cultureInfo); + return result == null ? "" : result; + } + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class CourseClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public CourseClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -1237,23 +1547,36 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); /// A server side error occurred. - public virtual System.Threading.Tasks.Task UpdateAsync(long id, Course requestDto) + public virtual System.Threading.Tasks.Task UpdateAsync(long id, CourseRequest requestDto) { return UpdateAsync(id, requestDto, System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task UpdateAsync(long id, Course requestDto, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task UpdateAsync(long id, CourseRequest requestDto, System.Threading.CancellationToken cancellationToken) { if (id == null) throw new System.ArgumentNullException("id"); @@ -1267,7 +1590,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(long id, Co { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -1275,7 +1598,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(long id, Co request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/courses/{id}" urlBuilder_.Append("api/courses/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -1305,7 +1628,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(long id, Co var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -1354,7 +1677,7 @@ public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Thr request_.Method = new System.Net.Http.HttpMethod("DELETE"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/courses/{id}" urlBuilder_.Append("api/courses/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -1407,14 +1730,14 @@ public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Thr } /// A server side error occurred. - public virtual System.Threading.Tasks.Task GetByIdAsync(long id) + public virtual System.Threading.Tasks.Task GetByIdAsync(long id) { return GetByIdAsync(id, System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, System.Threading.CancellationToken cancellationToken) { if (id == null) throw new System.ArgumentNullException("id"); @@ -1429,7 +1752,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, S request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/courses/{id}" urlBuilder_.Append("api/courses/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -1459,7 +1782,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, S var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -1487,14 +1810,14 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, S } /// A server side error occurred. - public virtual System.Threading.Tasks.Task CreateAsync(Course requestDto) + public virtual System.Threading.Tasks.Task CreateAsync(CourseRequest requestDto) { return CreateAsync(requestDto, System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task CreateAsync(Course requestDto, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task CreateAsync(CourseRequest requestDto, System.Threading.CancellationToken cancellationToken) { if (requestDto == null) throw new System.ArgumentNullException("requestDto"); @@ -1505,7 +1828,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Course requ { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -1513,7 +1836,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Course requ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/courses" urlBuilder_.Append("api/courses"); @@ -1542,7 +1865,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Course requ var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -1570,14 +1893,14 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Course requ } /// A server side error occurred. - public virtual System.Threading.Tasks.Task> GetAllAsync() + public virtual System.Threading.Tasks.Task> GetAllAsync() { return GetAllAsync(System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task> GetAllAsync(System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task> GetAllAsync(System.Threading.CancellationToken cancellationToken) { var client_ = _httpClient; var disposeClient_ = false; @@ -1589,7 +1912,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Course requ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/courses" urlBuilder_.Append("api/courses"); @@ -1618,7 +1941,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Course requ var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -1668,7 +1991,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Course requ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/courses/{id}/exercises" urlBuilder_.Append("api/courses/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -1712,10 +2035,6 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Course requ throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); } } - catch (Exception ex) - { - throw new ApiException(ex.Message, 400, "responseData_", null, null); - } finally { if (disposeResponse_) @@ -1753,7 +2072,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Course requ request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/courses/{id}/groups" urlBuilder_.Append("api/courses/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -1923,17 +2242,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class DashboardClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public DashboardClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -1943,10 +2269,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -1974,7 +2313,7 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/dashboard/{subjectId}" urlBuilder_.Append("api/dashboard/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(subjectId, System.Globalization.CultureInfo.InvariantCulture))); @@ -2143,17 +2482,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ExerciseClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public ExerciseClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -2163,10 +2509,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -2193,7 +2552,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(l { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -2201,7 +2560,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(l request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/exercises/{id}" urlBuilder_.Append("api/exercises/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -2280,7 +2639,7 @@ public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Thr request_.Method = new System.Net.Http.HttpMethod("DELETE"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/exercises/{id}" urlBuilder_.Append("api/exercises/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -2355,7 +2714,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync( request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/exercises/{id}" urlBuilder_.Append("api/exercises/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -2431,7 +2790,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(E { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -2439,7 +2798,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(E request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/exercises" urlBuilder_.Append("api/exercises"); @@ -2515,7 +2874,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(E request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/exercises" urlBuilder_.Append("api/exercises"); @@ -2594,7 +2953,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(E request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/exercises/{id}/assignments" urlBuilder_.Append("api/exercises/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -2675,7 +3034,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(E request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/exercises/{id}/scoreTypes" urlBuilder_.Append("api/exercises/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -2733,19 +3092,176 @@ public virtual async System.Threading.Tasks.Task CreateAsync(E } } + protected struct ObjectResponseResult + { + public ObjectResponseResult(T responseObject, string responseText) + { + this.Object = responseObject; + this.Text = responseText; + } + + public T Object { get; } + + public string Text { get; } + } + + public bool ReadResponseAsString { get; set; } + + protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Threading.CancellationToken cancellationToken) + { + if (response == null || response.Content == null) + { + return new ObjectResponseResult(default(T), string.Empty); + } + + if (ReadResponseAsString) + { + var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject(responseText, JsonSerializerSettings); + return new ObjectResponseResult(typedBody, responseText); + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body string as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception); + } + } + else + { + try + { + using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + using (var streamReader = new System.IO.StreamReader(responseStream)) + using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader)) + { + var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings); + var typedBody = serializer.Deserialize(jsonTextReader); + return new ObjectResponseResult(typedBody, string.Empty); + } + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body stream as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception); + } + } + } + + private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo) + { + if (value == null) + { + return ""; + } + + if (value is System.Enum) + { + var name = System.Enum.GetName(value.GetType(), value); + if (name != null) + { + var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); + if (field != null) + { + var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) + as System.Runtime.Serialization.EnumMemberAttribute; + if (attribute != null) + { + return attribute.Value != null ? attribute.Value : name; + } + } + + var converted = System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo)); + return converted == null ? string.Empty : converted; + } + } + else if (value is bool) + { + return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant(); + } + else if (value is byte[]) + { + return System.Convert.ToBase64String((byte[]) value); + } + else if (value is string[]) + { + return string.Join(",", (string[])value); + } + else if (value.GetType().IsArray) + { + var valueArray = (System.Array)value; + var valueTextArray = new string[valueArray.Length]; + for (var i = 0; i < valueArray.Length; i++) + { + valueTextArray[i] = ConvertToString(valueArray.GetValue(i), cultureInfo); + } + return string.Join(",", valueTextArray); + } + + var result = System.Convert.ToString(value, cultureInfo); + return result == null ? "" : result; + } + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class GitHubAppClient + { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + + private System.Net.Http.HttpClient _httpClient; + private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; + + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public GitHubAppClient(System.Net.Http.HttpClient httpClient) + #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + BaseUrl = "http://localhost:5180"; + _httpClient = httpClient; + Initialize(); + } + + private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() + { + var settings = new Newtonsoft.Json.JsonSerializerSettings(); + UpdateJsonSerializerSettings(settings); + return settings; + } + + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } + + static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + + partial void Initialize(); + + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); + partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); + /// A server side error occurred. - public virtual System.Threading.Tasks.Task ExportToCsvAsync(long id) + public virtual System.Threading.Tasks.Task CreateGitHubAppAsync(string code) { - return ExportToCsvAsync(id, System.Threading.CancellationToken.None); + return CreateGitHubAppAsync(code, System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task ExportToCsvAsync(long id, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task CreateGitHubAppAsync(string code, System.Threading.CancellationToken cancellationToken) { - if (id == null) - throw new System.ArgumentNullException("id"); - var client_ = _httpClient; var disposeClient_ = false; try @@ -2753,13 +3269,18 @@ public virtual async System.Threading.Tasks.Task ExportToCsvAsync(long id, Syste using (var request_ = new System.Net.Http.HttpRequestMessage()) { request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/octet-stream")); var urlBuilder_ = new System.Text.StringBuilder(); - - // Operation Path: "api/exercises/{id}/export" - urlBuilder_.Append("api/exercises/"); - urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); - urlBuilder_.Append("/export"); + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); + // Operation Path: "api/github" + urlBuilder_.Append("api/github"); + urlBuilder_.Append('?'); + if (code != null) + { + urlBuilder_.Append(System.Uri.EscapeDataString("code")).Append('=').Append(System.Uri.EscapeDataString(ConvertToString(code, System.Globalization.CultureInfo.InvariantCulture))).Append('&'); + } + urlBuilder_.Length--; PrepareRequest(client_, request_, urlBuilder_); @@ -2784,9 +3305,12 @@ public virtual async System.Threading.Tasks.Task ExportToCsvAsync(long id, Syste ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 200 || status_ == 206) { - return; + var responseStream_ = response_.Content == null ? System.IO.Stream.Null : await response_.Content.ReadAsStreamAsync().ConfigureAwait(false); + var fileResponse_ = new FileResponse(status_, headers_, responseStream_, null, response_); + disposeClient_ = false; disposeResponse_ = false; // response and client are disposed by FileResponse + return fileResponse_; } else { @@ -2920,17 +3444,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class GroupClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public GroupClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -2940,10 +3471,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -2970,7 +3514,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(long { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -2978,7 +3522,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(long request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/groups/{id}" urlBuilder_.Append("api/groups/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -3057,7 +3601,7 @@ public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Thr request_.Method = new System.Net.Http.HttpMethod("DELETE"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/groups/{id}" urlBuilder_.Append("api/groups/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -3132,7 +3676,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(lon request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/groups/{id}" urlBuilder_.Append("api/groups/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -3208,7 +3752,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Grou { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -3216,7 +3760,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Grou request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/groups" urlBuilder_.Append("api/groups"); @@ -3292,7 +3836,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Grou request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/groups" urlBuilder_.Append("api/groups"); @@ -3371,7 +3915,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Grou request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/groups/{id}/teachers" urlBuilder_.Append("api/groups/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -3452,7 +3996,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Grou request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/groups/{id}/students" urlBuilder_.Append("api/groups/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -3622,17 +4166,497 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class LanguageClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + + private System.Net.Http.HttpClient _httpClient; + private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; + + #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + public LanguageClient(System.Net.Http.HttpClient httpClient) + #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. + { + BaseUrl = "http://localhost:5180"; + _httpClient = httpClient; + Initialize(); + } + + private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() + { + var settings = new Newtonsoft.Json.JsonSerializerSettings(); + UpdateJsonSerializerSettings(settings); + return settings; + } + + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } + + static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + + partial void Initialize(); + + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); + partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); + + /// A server side error occurred. + public virtual System.Threading.Tasks.Task CreateAsync(Language requestDto) + { + return CreateAsync(requestDto, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task CreateAsync(Language requestDto, System.Threading.CancellationToken cancellationToken) + { + if (requestDto == null) + throw new System.ArgumentNullException("requestDto"); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); + var content_ = new System.Net.Http.StringContent(json_); + content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); + request_.Content = content_; + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + var urlBuilder_ = new System.Text.StringBuilder(); + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); + // Operation Path: "api/languages" + urlBuilder_.Append("api/languages"); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = new System.Collections.Generic.Dictionary>(); + foreach (var item_ in response_.Headers) + headers_[item_.Key] = item_.Value; + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + /// A server side error occurred. + public virtual System.Threading.Tasks.Task> GetAllAsync() + { + return GetAllAsync(System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task> GetAllAsync(System.Threading.CancellationToken cancellationToken) + { + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + var urlBuilder_ = new System.Text.StringBuilder(); + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); + // Operation Path: "api/languages" + urlBuilder_.Append("api/languages"); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = new System.Collections.Generic.Dictionary>(); + foreach (var item_ in response_.Headers) + headers_[item_.Key] = item_.Value; + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + /// A server side error occurred. + public virtual System.Threading.Tasks.Task DeleteAsync(long id) + { + return DeleteAsync(id, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Threading.CancellationToken cancellationToken) + { + if (id == null) + throw new System.ArgumentNullException("id"); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("DELETE"); + + var urlBuilder_ = new System.Text.StringBuilder(); + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); + // Operation Path: "api/languages/{id}" + urlBuilder_.Append("api/languages/"); + urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = new System.Collections.Generic.Dictionary>(); + foreach (var item_ in response_.Headers) + headers_[item_.Key] = item_.Value; + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 204) + { + return; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + /// A server side error occurred. + public virtual System.Threading.Tasks.Task GetByIdAsync(long id) + { + return GetByIdAsync(id, System.Threading.CancellationToken.None); + } + + /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. + /// A server side error occurred. + public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, System.Threading.CancellationToken cancellationToken) + { + if (id == null) + throw new System.ArgumentNullException("id"); + + var client_ = _httpClient; + var disposeClient_ = false; + try + { + using (var request_ = new System.Net.Http.HttpRequestMessage()) + { + request_.Method = new System.Net.Http.HttpMethod("GET"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + + var urlBuilder_ = new System.Text.StringBuilder(); + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); + // Operation Path: "api/languages/{id}" + urlBuilder_.Append("api/languages/"); + urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); + + PrepareRequest(client_, request_, urlBuilder_); + + var url_ = urlBuilder_.ToString(); + request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); + + PrepareRequest(client_, request_, url_); + + var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + var disposeResponse_ = true; + try + { + var headers_ = new System.Collections.Generic.Dictionary>(); + foreach (var item_ in response_.Headers) + headers_[item_.Key] = item_.Value; + if (response_.Content != null && response_.Content.Headers != null) + { + foreach (var item_ in response_.Content.Headers) + headers_[item_.Key] = item_.Value; + } + + ProcessResponse(client_, response_); + + var status_ = (int)response_.StatusCode; + if (status_ == 200) + { + var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); + if (objectResponse_.Object == null) + { + throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); + } + return objectResponse_.Object; + } + else + { + var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); + } + } + finally + { + if (disposeResponse_) + response_.Dispose(); + } + } + } + finally + { + if (disposeClient_) + client_.Dispose(); + } + } + + protected struct ObjectResponseResult + { + public ObjectResponseResult(T responseObject, string responseText) + { + this.Object = responseObject; + this.Text = responseText; + } + + public T Object { get; } + + public string Text { get; } + } + + public bool ReadResponseAsString { get; set; } + + protected virtual async System.Threading.Tasks.Task> ReadObjectResponseAsync(System.Net.Http.HttpResponseMessage response, System.Collections.Generic.IReadOnlyDictionary> headers, System.Threading.CancellationToken cancellationToken) + { + if (response == null || response.Content == null) + { + return new ObjectResponseResult(default(T), string.Empty); + } + + if (ReadResponseAsString) + { + var responseText = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + try + { + var typedBody = Newtonsoft.Json.JsonConvert.DeserializeObject(responseText, JsonSerializerSettings); + return new ObjectResponseResult(typedBody, responseText); + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body string as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, responseText, headers, exception); + } + } + else + { + try + { + using (var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) + using (var streamReader = new System.IO.StreamReader(responseStream)) + using (var jsonTextReader = new Newtonsoft.Json.JsonTextReader(streamReader)) + { + var serializer = Newtonsoft.Json.JsonSerializer.Create(JsonSerializerSettings); + var typedBody = serializer.Deserialize(jsonTextReader); + return new ObjectResponseResult(typedBody, string.Empty); + } + } + catch (Newtonsoft.Json.JsonException exception) + { + var message = "Could not deserialize the response body stream as " + typeof(T).FullName + "."; + throw new ApiException(message, (int)response.StatusCode, string.Empty, headers, exception); + } + } + } + + private string ConvertToString(object value, System.Globalization.CultureInfo cultureInfo) + { + if (value == null) + { + return ""; + } + + if (value is System.Enum) + { + var name = System.Enum.GetName(value.GetType(), value); + if (name != null) + { + var field = System.Reflection.IntrospectionExtensions.GetTypeInfo(value.GetType()).GetDeclaredField(name); + if (field != null) + { + var attribute = System.Reflection.CustomAttributeExtensions.GetCustomAttribute(field, typeof(System.Runtime.Serialization.EnumMemberAttribute)) + as System.Runtime.Serialization.EnumMemberAttribute; + if (attribute != null) + { + return attribute.Value != null ? attribute.Value : name; + } + } + + var converted = System.Convert.ToString(System.Convert.ChangeType(value, System.Enum.GetUnderlyingType(value.GetType()), cultureInfo)); + return converted == null ? string.Empty : converted; + } + } + else if (value is bool) + { + return System.Convert.ToString((bool)value, cultureInfo).ToLowerInvariant(); + } + else if (value is byte[]) + { + return System.Convert.ToBase64String((byte[]) value); + } + else if (value is string[]) + { + return string.Join(",", (string[])value); + } + else if (value.GetType().IsArray) + { + var valueArray = (System.Array)value; + var valueTextArray = new string[valueArray.Length]; + for (var i = 0; i < valueArray.Length; i++) + { + valueTextArray[i] = ConvertToString(valueArray.GetValue(i), cultureInfo); + } + return string.Join(",", valueTextArray); + } + + var result = System.Convert.ToString(value, cultureInfo); + return result == null ? "" : result; + } + } + + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class MoodleIntegrationClient + { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - public LanguageClient(System.Net.Http.HttpClient httpClient) + public MoodleIntegrationClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -3642,120 +4666,51 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); /// A server side error occurred. - public virtual System.Threading.Tasks.Task CreateAsync(Language requestDto) + public virtual System.Threading.Tasks.Task OidcAsync() { - return CreateAsync(requestDto, System.Threading.CancellationToken.None); + return OidcAsync(System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task CreateAsync(Language requestDto, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task OidcAsync(System.Threading.CancellationToken cancellationToken) { - if (requestDto == null) - throw new System.ArgumentNullException("requestDto"); - var client_ = _httpClient; var disposeClient_ = false; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); - var content_ = new System.Net.Http.StringContent(json_); - content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); - request_.Content = content_; + request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json"); request_.Method = new System.Net.Http.HttpMethod("POST"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); - - var urlBuilder_ = new System.Text.StringBuilder(); - - // Operation Path: "api/languages" - urlBuilder_.Append("api/languages"); - - PrepareRequest(client_, request_, urlBuilder_); - - var url_ = urlBuilder_.ToString(); - request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute); - - PrepareRequest(client_, request_, url_); - - var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - var disposeResponse_ = true; - try - { - var headers_ = new System.Collections.Generic.Dictionary>(); - foreach (var item_ in response_.Headers) - headers_[item_.Key] = item_.Value; - if (response_.Content != null && response_.Content.Headers != null) - { - foreach (var item_ in response_.Content.Headers) - headers_[item_.Key] = item_.Value; - } - - ProcessResponse(client_, response_); - - var status_ = (int)response_.StatusCode; - if (status_ == 200) - { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; - } - else - { - var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null); - } - } - finally - { - if (disposeResponse_) - response_.Dispose(); - } - } - } - finally - { - if (disposeClient_) - client_.Dispose(); - } - } - - /// A server side error occurred. - public virtual System.Threading.Tasks.Task> GetAllAsync() - { - return GetAllAsync(System.Threading.CancellationToken.None); - } - - /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. - /// A server side error occurred. - public virtual async System.Threading.Tasks.Task> GetAllAsync(System.Threading.CancellationToken cancellationToken) - { - var client_ = _httpClient; - var disposeClient_ = false; - try - { - using (var request_ = new System.Net.Http.HttpRequestMessage()) - { - request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/octet-stream")); var urlBuilder_ = new System.Text.StringBuilder(); - - // Operation Path: "api/languages" - urlBuilder_.Append("api/languages"); + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); + // Operation Path: "api/moodle/oidc" + urlBuilder_.Append("api/moodle/oidc"); PrepareRequest(client_, request_, urlBuilder_); @@ -3780,14 +4735,12 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Language ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 200 || status_ == 206) { - var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + var responseStream_ = response_.Content == null ? System.IO.Stream.Null : await response_.Content.ReadAsStreamAsync().ConfigureAwait(false); + var fileResponse_ = new FileResponse(status_, headers_, responseStream_, null, response_); + disposeClient_ = false; disposeResponse_ = false; // response and client are disposed by FileResponse + return fileResponse_; } else { @@ -3810,31 +4763,29 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Language } /// A server side error occurred. - public virtual System.Threading.Tasks.Task DeleteAsync(long id) + public virtual System.Threading.Tasks.Task CheckPlatformAnswerAsync() { - return DeleteAsync(id, System.Threading.CancellationToken.None); + return CheckPlatformAnswerAsync(System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task CheckPlatformAnswerAsync(System.Threading.CancellationToken cancellationToken) { - if (id == null) - throw new System.ArgumentNullException("id"); - var client_ = _httpClient; var disposeClient_ = false; try { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - request_.Method = new System.Net.Http.HttpMethod("DELETE"); + request_.Content = new System.Net.Http.StringContent(string.Empty, System.Text.Encoding.UTF8, "application/json"); + request_.Method = new System.Net.Http.HttpMethod("POST"); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/octet-stream")); var urlBuilder_ = new System.Text.StringBuilder(); - - // Operation Path: "api/languages/{id}" - urlBuilder_.Append("api/languages/"); - urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); + // Operation Path: "api/moodle" + urlBuilder_.Append("api/moodle"); PrepareRequest(client_, request_, urlBuilder_); @@ -3859,9 +4810,12 @@ public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Thr ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 204) + if (status_ == 200 || status_ == 206) { - return; + var responseStream_ = response_.Content == null ? System.IO.Stream.Null : await response_.Content.ReadAsStreamAsync().ConfigureAwait(false); + var fileResponse_ = new FileResponse(status_, headers_, responseStream_, null, response_); + disposeClient_ = false; disposeResponse_ = false; // response and client are disposed by FileResponse + return fileResponse_; } else { @@ -3884,18 +4838,15 @@ public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Thr } /// A server side error occurred. - public virtual System.Threading.Tasks.Task GetByIdAsync(long id) + public virtual System.Threading.Tasks.Task GetAsync() { - return GetByIdAsync(id, System.Threading.CancellationToken.None); + return GetAsync(System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task GetAsync(System.Threading.CancellationToken cancellationToken) { - if (id == null) - throw new System.ArgumentNullException("id"); - var client_ = _httpClient; var disposeClient_ = false; try @@ -3903,13 +4854,12 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, using (var request_ = new System.Net.Http.HttpRequestMessage()) { request_.Method = new System.Net.Http.HttpMethod("GET"); - request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); + request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/octet-stream")); var urlBuilder_ = new System.Text.StringBuilder(); - - // Operation Path: "api/languages/{id}" - urlBuilder_.Append("api/languages/"); - urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); + // Operation Path: "api/moodle" + urlBuilder_.Append("api/moodle"); PrepareRequest(client_, request_, urlBuilder_); @@ -3934,14 +4884,12 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, ProcessResponse(client_, response_); var status_ = (int)response_.StatusCode; - if (status_ == 200) + if (status_ == 200 || status_ == 206) { - var objectResponse_ = await ReadObjectResponseAsync(response_, headers_, cancellationToken).ConfigureAwait(false); - if (objectResponse_.Object == null) - { - throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); - } - return objectResponse_.Object; + var responseStream_ = response_.Content == null ? System.IO.Stream.Null : await response_.Content.ReadAsStreamAsync().ConfigureAwait(false); + var fileResponse_ = new FileResponse(status_, headers_, responseStream_, null, response_); + disposeClient_ = false; disposeResponse_ = false; // response and client are disposed by FileResponse + return fileResponse_; } else { @@ -4075,17 +5023,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PullRequestClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public PullRequestClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -4095,10 +5050,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -4126,7 +5094,7 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/pullrequests/{id}/scores" urlBuilder_.Append("api/pullrequests/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -4296,17 +5264,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SemesterClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public SemesterClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -4316,10 +5291,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -4343,7 +5331,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Semester { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -4351,7 +5339,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Semester request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/semesters" urlBuilder_.Append("api/semesters"); @@ -4427,7 +5415,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Semester request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/semesters" urlBuilder_.Append("api/semesters"); @@ -4505,7 +5493,7 @@ public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Thr request_.Method = new System.Net.Http.HttpMethod("DELETE"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/semesters/{id}" urlBuilder_.Append("api/semesters/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -4580,7 +5568,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/semesters/{id}" urlBuilder_.Append("api/semesters/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -4749,17 +5737,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class StudentClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public StudentClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -4769,10 +5764,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -4797,7 +5805,7 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/students" urlBuilder_.Append("api/students"); @@ -4872,7 +5880,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(St { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -4880,7 +5888,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(St request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/students" urlBuilder_.Append("api/students"); @@ -4959,7 +5967,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(l request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/students/{id}" urlBuilder_.Append("api/students/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -5039,7 +6047,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(l request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/students/{id}/groups" urlBuilder_.Append("api/students/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -5120,7 +6128,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(l request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/students/{id}/assignments" urlBuilder_.Append("api/students/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -5290,17 +6298,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubjectClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public SubjectClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -5310,10 +6325,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -5340,7 +6368,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(lo { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -5348,7 +6376,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(lo request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/subjects/{id}" urlBuilder_.Append("api/subjects/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -5427,7 +6455,7 @@ public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Thr request_.Method = new System.Net.Http.HttpMethod("DELETE"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/subjects/{id}" urlBuilder_.Append("api/subjects/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -5502,7 +6530,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(l request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/subjects/{id}" urlBuilder_.Append("api/subjects/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -5578,7 +6606,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Su { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -5586,7 +6614,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Su request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/subjects" urlBuilder_.Append("api/subjects"); @@ -5662,7 +6690,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Su request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/subjects" urlBuilder_.Append("api/subjects"); @@ -5719,14 +6747,14 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Su } /// A server side error occurred. - public virtual System.Threading.Tasks.Task> GetAllCoursesByIdAsync(long id) + public virtual System.Threading.Tasks.Task> GetAllCoursesByIdAsync(long id) { return GetAllCoursesByIdAsync(id, System.Threading.CancellationToken.None); } /// A cancellation token that can be used by other objects or threads to receive notice of cancellation. /// A server side error occurred. - public virtual async System.Threading.Tasks.Task> GetAllCoursesByIdAsync(long id, System.Threading.CancellationToken cancellationToken) + public virtual async System.Threading.Tasks.Task> GetAllCoursesByIdAsync(long id, System.Threading.CancellationToken cancellationToken) { if (id == null) throw new System.ArgumentNullException("id"); @@ -5741,7 +6769,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Su request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/subjects/{id}/courses" urlBuilder_.Append("api/subjects/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -5772,7 +6800,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Su var status_ = (int)response_.StatusCode; if (status_ == 200) { - var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); + var objectResponse_ = await ReadObjectResponseAsync>(response_, headers_, cancellationToken).ConfigureAwait(false); if (objectResponse_.Object == null) { throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null); @@ -5822,7 +6850,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Su request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/subjects/{id}/teachers" urlBuilder_.Append("api/subjects/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -5907,7 +6935,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(Su request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/subjects/{subjectId}/teachers/{teacherId}" urlBuilder_.Append("api/subjects/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(subjectId, System.Globalization.CultureInfo.InvariantCulture))); @@ -5991,7 +7019,7 @@ public virtual async System.Threading.Tasks.Task DeleteTeacherFromSubjectByIdAsy request_.Method = new System.Net.Http.HttpMethod("DELETE"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/subjects/{subjectId}/teachers/{teacherId}" urlBuilder_.Append("api/subjects/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(subjectId, System.Globalization.CultureInfo.InvariantCulture))); @@ -6157,17 +7185,24 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class UserClient { + #pragma warning disable 8618 + private string _baseUrl; + #pragma warning restore 8618 + private System.Net.Http.HttpClient _httpClient; private static System.Lazy _settings = new System.Lazy(CreateSerializerSettings, true); + private Newtonsoft.Json.JsonSerializerSettings _instanceSettings; #pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. public UserClient(System.Net.Http.HttpClient httpClient) #pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. { + BaseUrl = "http://localhost:5180"; _httpClient = httpClient; + Initialize(); } private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() @@ -6177,10 +7212,23 @@ private static Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings() return settings; } - protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } } + public string BaseUrl + { + get { return _baseUrl; } + set + { + _baseUrl = value; + if (!string.IsNullOrEmpty(_baseUrl) && !_baseUrl.EndsWith("/")) + _baseUrl += '/'; + } + } + + protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _instanceSettings ?? _settings.Value; } } static partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings); + partial void Initialize(); + partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, string url); partial void PrepareRequest(System.Net.Http.HttpClient client, System.Net.Http.HttpRequestMessage request, System.Text.StringBuilder urlBuilder); partial void ProcessResponse(System.Net.Http.HttpClient client, System.Net.Http.HttpResponseMessage response); @@ -6207,7 +7255,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(long id, User { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -6215,7 +7263,7 @@ public virtual async System.Threading.Tasks.Task UpdateAsync(long id, User request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/users/{id}" urlBuilder_.Append("api/users/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -6294,7 +7342,7 @@ public virtual async System.Threading.Tasks.Task DeleteAsync(long id, System.Thr request_.Method = new System.Net.Http.HttpMethod("DELETE"); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/users/{id}" urlBuilder_.Append("api/users/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -6369,7 +7417,7 @@ public virtual async System.Threading.Tasks.Task GetByIdAsync(long id, Sys request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/users/{id}" urlBuilder_.Append("api/users/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -6445,7 +7493,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(User requestD { using (var request_ = new System.Net.Http.HttpRequestMessage()) { - var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, _settings.Value); + var json_ = Newtonsoft.Json.JsonConvert.SerializeObject(requestDto, JsonSerializerSettings); var content_ = new System.Net.Http.StringContent(json_); content_.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/json"); request_.Content = content_; @@ -6453,7 +7501,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(User requestD request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/users" urlBuilder_.Append("api/users"); @@ -6529,7 +7577,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(User requestD request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/users" urlBuilder_.Append("api/users"); @@ -6608,7 +7656,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(User requestD request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/users/{id}/groups" urlBuilder_.Append("api/users/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -6689,7 +7737,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(User requestD request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/users/{id}/subjects" urlBuilder_.Append("api/users/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -6770,7 +7818,7 @@ public virtual async System.Threading.Tasks.Task CreateAsync(User requestD request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "api/users/{id}/pullrequests" urlBuilder_.Append("api/users/"); urlBuilder_.Append(System.Uri.EscapeDataString(ConvertToString(id, System.Globalization.CultureInfo.InvariantCulture))); @@ -6848,7 +7896,7 @@ public virtual async System.Threading.Tasks.Task GetCurrentUserAsync(Syste request_.Headers.Accept.Add(System.Net.Http.Headers.MediaTypeWithQualityHeaderValue.Parse("application/json")); var urlBuilder_ = new System.Text.StringBuilder(); - + if (!string.IsNullOrEmpty(_baseUrl)) urlBuilder_.Append(_baseUrl); // Operation Path: "me" urlBuilder_.Append("me"); @@ -7016,7 +8064,7 @@ private string ConvertToString(object value, System.Globalization.CultureInfo cu } } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Assignment { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7036,7 +8084,7 @@ public partial class Assignment } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PullRequest { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7062,7 +8110,7 @@ public partial class PullRequest } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum PullRequestStatus { @@ -7074,13 +8122,13 @@ public enum PullRequestStatus } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AssignmentAccepted : AssignmentEventBase { } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AssignmentEventBase { [Newtonsoft.Json.JsonProperty("gitHubRepositoryUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7088,7 +8136,7 @@ public partial class AssignmentEventBase } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PullRequestOpened : AssignmentEventBase { [Newtonsoft.Json.JsonProperty("pullRequestUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7102,7 +8150,7 @@ public partial class PullRequestOpened : AssignmentEventBase } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class CiEvaluationCompleted : AssignmentEventBase { [Newtonsoft.Json.JsonProperty("pullRequestUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7119,7 +8167,7 @@ public partial class CiEvaluationCompleted : AssignmentEventBase } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class TeacherAssigned : AssignmentEventBase { [Newtonsoft.Json.JsonProperty("pullRequestUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7130,7 +8178,7 @@ public partial class TeacherAssigned : AssignmentEventBase } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class AssignmentGradedByTeacher : AssignmentEventBase { [Newtonsoft.Json.JsonProperty("pullRequestUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7147,7 +8195,7 @@ public partial class AssignmentGradedByTeacher : AssignmentEventBase } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PullRequestStatusChanged : AssignmentEventBase { [Newtonsoft.Json.JsonProperty("pullRequestUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7158,8 +8206,37 @@ public partial class PullRequestStatusChanged : AssignmentEventBase } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] - public partial class Course + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class ProblemDetails + { + [Newtonsoft.Json.JsonProperty("type", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Type { get; set; } + + [Newtonsoft.Json.JsonProperty("title", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Title { get; set; } + + [Newtonsoft.Json.JsonProperty("status", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public int? Status { get; set; } + + [Newtonsoft.Json.JsonProperty("detail", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Detail { get; set; } + + [Newtonsoft.Json.JsonProperty("instance", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Instance { get; set; } + + private System.Collections.Generic.IDictionary _additionalProperties; + + [Newtonsoft.Json.JsonExtensionData] + public System.Collections.Generic.IDictionary AdditionalProperties + { + get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary()); } + set { _additionalProperties = value; } + } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class CourseResponse { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public long Id { get; set; } @@ -7167,8 +8244,11 @@ public partial class Course [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public string Name { get; set; } - [Newtonsoft.Json.JsonProperty("moodleCourseId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] - public string MoodleCourseId { get; set; } + [Newtonsoft.Json.JsonProperty("moodleClientId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string MoodleClientId { get; set; } + + [Newtonsoft.Json.JsonProperty("publicKey", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string PublicKey { get; set; } [Newtonsoft.Json.JsonProperty("subjectId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public long SubjectId { get; set; } @@ -7181,7 +8261,7 @@ public partial class Course } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Semester { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7192,7 +8272,7 @@ public partial class Semester } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Language { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7203,7 +8283,30 @@ public partial class Language } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class CourseRequest + { + [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long Id { get; set; } + + [Newtonsoft.Json.JsonProperty("name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string Name { get; set; } + + [Newtonsoft.Json.JsonProperty("moodleClientId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string MoodleClientId { get; set; } + + [Newtonsoft.Json.JsonProperty("subjectId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public long SubjectId { get; set; } + + [Newtonsoft.Json.JsonProperty("semester", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Semester Semester { get; set; } + + [Newtonsoft.Json.JsonProperty("language", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public Language Language { get; set; } + + } + + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ExerciseResponse { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7218,6 +8321,12 @@ public partial class ExerciseResponse [Newtonsoft.Json.JsonProperty("dueDate", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public System.DateTimeOffset DueDate { get; set; } + [Newtonsoft.Json.JsonProperty("moodleScoreNamePrefix", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string MoodleScoreNamePrefix { get; set; } + + [Newtonsoft.Json.JsonProperty("classroomUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string ClassroomUrl { get; set; } + [Newtonsoft.Json.JsonProperty("courseId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public long CourseId { get; set; } @@ -7226,7 +8335,7 @@ public partial class ExerciseResponse } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class GroupResponse { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7240,7 +8349,7 @@ public partial class GroupResponse } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Dashboard { [Newtonsoft.Json.JsonProperty("assignmentName", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7263,7 +8372,7 @@ public partial class Dashboard } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class PullRequestForDashboard { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7292,7 +8401,7 @@ public partial class PullRequestForDashboard } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class Score { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7318,7 +8427,7 @@ public partial class Score } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ScoreType { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7329,7 +8438,7 @@ public partial class ScoreType } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ExerciseRequest { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7344,6 +8453,12 @@ public partial class ExerciseRequest [Newtonsoft.Json.JsonProperty("dueDate", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public System.DateTimeOffset DueDate { get; set; } + [Newtonsoft.Json.JsonProperty("moodleScoreNamePrefix", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string MoodleScoreNamePrefix { get; set; } + + [Newtonsoft.Json.JsonProperty("classroomUrl", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] + public string ClassroomUrl { get; set; } + [Newtonsoft.Json.JsonProperty("courseId", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] public long CourseId { get; set; } @@ -7352,7 +8467,7 @@ public partial class ExerciseRequest } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ScoreTypeExercise { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7369,7 +8484,7 @@ public partial class ScoreTypeExercise } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class GroupRequest { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7386,7 +8501,7 @@ public partial class GroupRequest } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class User { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7409,7 +8524,7 @@ public partial class User } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public enum UserType { @@ -7421,7 +8536,7 @@ public enum UserType } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class StudentResponse { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7438,7 +8553,7 @@ public partial class StudentResponse } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class StudentRequest { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7458,7 +8573,7 @@ public partial class StudentRequest } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubjectResponse { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7475,7 +8590,7 @@ public partial class SubjectResponse } - [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class SubjectRequest { [Newtonsoft.Json.JsonProperty("id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)] @@ -7498,9 +8613,44 @@ public partial class SubjectRequest } + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] + public partial class FileResponse : System.IDisposable + { + private System.IDisposable _client; + private System.IDisposable _response; + + public int StatusCode { get; private set; } + + public System.Collections.Generic.IReadOnlyDictionary> Headers { get; private set; } + + public System.IO.Stream Stream { get; private set; } + + public bool IsPartial + { + get { return StatusCode == 206; } + } + + public FileResponse(int statusCode, System.Collections.Generic.IReadOnlyDictionary> headers, System.IO.Stream stream, System.IDisposable client, System.IDisposable response) + { + StatusCode = statusCode; + Headers = headers; + Stream = stream; + _client = client; + _response = response; + } + + public void Dispose() + { + Stream.Dispose(); + if (_response != null) + _response.Dispose(); + if (_client != null) + _client.Dispose(); + } + } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ApiException : System.Exception { public int StatusCode { get; private set; } @@ -7523,7 +8673,7 @@ public override string ToString() } } - [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.0.7.0 (NJsonSchema v11.0.0.0 (Newtonsoft.Json v13.0.0.0))")] + [System.CodeDom.Compiler.GeneratedCode("NSwag", "14.4.0.0 (NJsonSchema v11.3.2.0 (Newtonsoft.Json v13.0.0.0))")] public partial class ApiException : ApiException { public TResult Result { get; private set; } @@ -7545,6 +8695,8 @@ public ApiException(string message, int statusCode, string response, System.Coll #pragma warning restore 1591 #pragma warning restore 8073 #pragma warning restore 3016 +#pragma warning restore 8600 +#pragma warning restore 8602 #pragma warning restore 8603 #pragma warning restore 8604 #pragma warning restore 8625 diff --git a/grade-management-new/GradeManagement.Client/Pages/Courses.razor b/grade-management-new/GradeManagement.Client/Pages/Courses.razor index 47e6287..a2901d6 100644 --- a/grade-management-new/GradeManagement.Client/Pages/Courses.razor +++ b/grade-management-new/GradeManagement.Client/Pages/Courses.razor @@ -9,6 +9,7 @@ @inject CourseClient CourseClient @inject SubjectClient SubjectClient @inject NavigationManager NavigationManager +@inject IJSRuntime JsRuntime @attribute [Authorize(Policy = Policy.RequireAdmin)] @@ -29,11 +30,12 @@ Courses - + - + @context.Item.Semester.Name @@ -50,17 +52,27 @@ - + + + + Copy + + + + - + @code { - private ICollection _courses = new List(); + private ICollection _courses = new List(); private LoadingComponent loadingComponentRef; - private void RowClickEvent(DataGridRowClickEventArgs args) + private void RowClickEvent(DataGridRowClickEventArgs args) { var courseId = args.Item.Id; NavigationManager.NavigateTo($"/courses/{courseId}"); @@ -79,29 +91,38 @@ var result = await dialog.Result ?? DialogResult.Cancel(); if (!result.Canceled && result.Data != null) { - var newCourse = result.Data as Course; + var newCourse = result.Data as CourseRequest; newCourse.SubjectId = SubjectService.CurrentSubject.Id; await CourseClient.CreateAsync(newCourse); await _loading(); } } - private async Task StartEditing(CellContext context) + private async Task StartEditing(CellContext context) { await context.Actions.StartEditingItemAsync(); StateHasChanged(); } - private async Task CommittedItemChanges(Course items) + private async Task CommittedItemChanges(CourseResponse item) { - await CourseClient.UpdateAsync(items.Id, items); + CourseRequest courseRequest = new CourseRequest() + { + Id = item.Id, + Language = item.Language, + MoodleClientId = item.MoodleClientId, + Name = item.Name, + Semester = item.Semester, + SubjectId = item.SubjectId + }; + await CourseClient.UpdateAsync(courseRequest.Id, courseRequest); //StateHasChanged(); SnackbarService.ShowEditSuccess(); //await loadingComponentRef.StartLoading(); _courses = await SubjectClient.GetAllCoursesByIdAsync(SubjectService.CurrentSubject.Id); } - private async Task DeleteItem(Course item) + private async Task DeleteItem(CourseResponse item) { await CourseClient.DeleteAsync(item.Id); SnackbarService.ShowDeleteSuccess(); @@ -124,4 +145,18 @@ SubjectService.OnChange -= OnSubjectChanged; } + private async Task CopyToClipboard(string publicKey) + { + try + { + await JsRuntime.InvokeVoidAsync("navigator.clipboard.writeText", publicKey); + SnackbarService.ShowSuccess("Public key copied to clipboard!"); + } + catch (JSException) + { + await JsRuntime.InvokeVoidAsync("copyTextFallback", publicKey); + SnackbarService.ShowSuccess("Public key copied to clipboard!"); + } + } + } diff --git a/grade-management-new/GradeManagement.Client/Pages/CreationWizard.razor b/grade-management-new/GradeManagement.Client/Pages/CreationWizard.razor index 3c85b8a..ba2abb1 100644 --- a/grade-management-new/GradeManagement.Client/Pages/CreationWizard.razor +++ b/grade-management-new/GradeManagement.Client/Pages/CreationWizard.razor @@ -1,4 +1,8 @@ @page "/wizard" +@using System.Text.Json +@using GradeManagement.Client.Components.NewDialogs +@using GradeManagement.Shared.Dtos.GitHubManifest +@using MudExtensions @layout AuthenticatedLayout @inject CrudSnackbarService SnackbarService @inject IDialogService DialogService @@ -7,14 +11,11 @@ @inject LanguageClient LanguageClient @inject SemesterClient SemesterClient @inject CourseClient CourseClient +@inject HttpClient Http @inject NavigationManager NavigationManager +@inject IJSRuntime JSRuntime @attribute [Authorize(Policy = Policy.RequireTeacher)] -@using GradeManagement.Client.Components.NewDialogs -@using MudExtensions -@using MudBlazor.Extensions -@using MudExtensions.Utilities -