diff --git a/rubberduckvba.Server/Api/Admin/AdminController.cs b/rubberduckvba.Server/Api/Admin/AdminController.cs index 4993c72..cf48508 100644 --- a/rubberduckvba.Server/Api/Admin/AdminController.cs +++ b/rubberduckvba.Server/Api/Admin/AdminController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; @@ -13,6 +14,7 @@ public class AdminController(ConfigurationOptions options, HangfireLauncherServi /// /// The unique identifier of the enqueued job. [Authorize("github")] + [EnableCors("CorsPolicy")] [HttpPost("admin/update/xmldoc")] public IActionResult UpdateXmldocContent() { @@ -25,6 +27,7 @@ public IActionResult UpdateXmldocContent() /// /// The unique identifier of the enqueued job. [Authorize("github")] + [EnableCors("CorsPolicy")] [HttpPost("admin/update/tags")] public IActionResult UpdateTagMetadata() { diff --git a/rubberduckvba.Server/Api/Admin/WebhookController.cs b/rubberduckvba.Server/Api/Admin/WebhookController.cs index 8f99aab..6ded8a6 100644 --- a/rubberduckvba.Server/Api/Admin/WebhookController.cs +++ b/rubberduckvba.Server/Api/Admin/WebhookController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using System.Text.Json; @@ -21,6 +22,7 @@ public WebhookController( } [Authorize("webhook")] + [EnableCors("webhookPolicy")] [HttpPost("webhook/github")] public async Task GitHub([FromBody] dynamic body) => GuardInternalAction(() => diff --git a/rubberduckvba.Server/Api/Auth/AuthController.cs b/rubberduckvba.Server/Api/Auth/AuthController.cs index 05a8818..92247ab 100644 --- a/rubberduckvba.Server/Api/Auth/AuthController.cs +++ b/rubberduckvba.Server/Api/Auth/AuthController.cs @@ -1,4 +1,5 @@ using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Octokit; @@ -70,6 +71,7 @@ public IActionResult Index() } [HttpPost("auth/signin")] + [EnableCors("CorsPolicy")] [AllowAnonymous] public IActionResult SessionSignIn(SignInViewModel vm) { @@ -106,6 +108,7 @@ public IActionResult SessionSignIn(SignInViewModel vm) } [HttpPost("auth/github")] + [EnableCors("CorsPolicy")] [AllowAnonymous] public IActionResult OnGitHubCallback(SignInViewModel vm) { diff --git a/rubberduckvba.Server/ContentSynchronization/Pipeline/Sections/SyncTags/LoadGitHubTagsBlock.cs b/rubberduckvba.Server/ContentSynchronization/Pipeline/Sections/SyncTags/LoadGitHubTagsBlock.cs index d9dfc63..1fca8e9 100644 --- a/rubberduckvba.Server/ContentSynchronization/Pipeline/Sections/SyncTags/LoadGitHubTagsBlock.cs +++ b/rubberduckvba.Server/ContentSynchronization/Pipeline/Sections/SyncTags/LoadGitHubTagsBlock.cs @@ -16,7 +16,7 @@ public LoadGitHubTagsBlock(PipelineSection parent, CancellationToke public override async Task TransformAsync(SyncRequestParameters input) { - var githubTags = await _github.GetAllTagsAsync(); // does not get the assets + var githubTags = await _github.GetAllTagsAsync(Context.RubberduckDbMain.Name); var (gitHubMain, gitHubNext, gitHubOthers) = githubTags.GetLatestTags(); Context.LoadGitHubTags(gitHubMain, gitHubNext, gitHubOthers); diff --git a/rubberduckvba.Server/ContentSynchronization/Pipeline/Sections/SyncXmldoc/SyncXmldocSection.cs b/rubberduckvba.Server/ContentSynchronization/Pipeline/Sections/SyncXmldoc/SyncXmldocSection.cs index 3cd19de..0aa4ab9 100644 --- a/rubberduckvba.Server/ContentSynchronization/Pipeline/Sections/SyncXmldoc/SyncXmldocSection.cs +++ b/rubberduckvba.Server/ContentSynchronization/Pipeline/Sections/SyncXmldoc/SyncXmldocSection.cs @@ -90,7 +90,8 @@ protected override async Task ActionAsync(SyncRequestParameters input) { Context.LoadParameters(input); - var githubTags = await _github.GetAllTagsAsync(); + var dbMain = await _content.GetLatestTagAsync(RepositoryId.Rubberduck, includePreRelease: false); + var githubTags = await _github.GetAllTagsAsync(dbMain.Name); // LoadInspectionDefaultConfig var config = await _github.GetCodeAnalysisDefaultsConfigAsync(); @@ -115,7 +116,6 @@ await Task.WhenAll([ await Task.Delay(TimeSpan.FromSeconds(2)); // just in case the tags job was scheduled at/around the same time - var dbMain = await _content.GetLatestTagAsync(RepositoryId.Rubberduck, includePreRelease: false); var dbNext = await _content.GetLatestTagAsync(RepositoryId.Rubberduck, includePreRelease: true); var dbTags = _tagServices.GetAllTags().ToDictionary(e => e.Name); diff --git a/rubberduckvba.Server/Program.cs b/rubberduckvba.Server/Program.cs index 3bc58fb..7c628c5 100644 --- a/rubberduckvba.Server/Program.cs +++ b/rubberduckvba.Server/Program.cs @@ -45,7 +45,7 @@ public static void Main(string[] args) builder.Services.AddCors(builder => { - builder.AddDefaultPolicy(policy => + builder.AddPolicy("CorsPolicy", policy => { policy .SetIsOriginAllowed(origin => true) @@ -54,22 +54,6 @@ public static void Main(string[] args) .AllowCredentials() .Build(); }); - - builder.AddPolicy("webhookPolicy", policy => - { - policy -#if DEBUG - .SetIsOriginAllowed(origin => true) -#else - .SetIsOriginAllowedToAllowWildcardSubdomains() - .WithOrigins("*.github.com") -#endif - .WithHeaders("Content-Type", "X-GitHub-Event", "X-GitHub-Delivery", "X-GitHub-Hook-ID", "X-Hub-Signature", "X-Hub-Signature256") - .WithMethods("POST") - .DisallowCredentials() - .SetPreflightMaxAge(TimeSpan.FromHours(48)) - .Build(); - }); }); builder.Services.AddAuthentication(options => diff --git a/rubberduckvba.Server/Services/GitHubClientService.cs b/rubberduckvba.Server/Services/GitHubClientService.cs index 6260e96..479c131 100644 --- a/rubberduckvba.Server/Services/GitHubClientService.cs +++ b/rubberduckvba.Server/Services/GitHubClientService.cs @@ -6,6 +6,7 @@ using rubberduckvba.Server.ContentSynchronization.XmlDoc.Schema; using rubberduckvba.Server.Model; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using System.Security.Claims; using System.Text; using System.Web; @@ -16,13 +17,20 @@ namespace rubberduckvba.Server.Services; public interface IGitHubClientService { Task ValidateTokenAsync(string token); - Task> GetAllTagsAsync(); + Task> GetAllTagsAsync(string? dbMainTagName); Task GetTagAsync(string? token, string name); Task> GetCodeAnalysisDefaultsConfigAsync(); } public class GitHubClientService(IOptions configuration, ILogger logger) : IGitHubClientService { + private class ReleaseComparer : IEqualityComparer + { + public bool Equals(Release? x, Release? y) => x?.Name == y?.Name; + + public int GetHashCode([DisallowNull] Release obj) => HashCode.Combine(obj.Name); + } + public async Task ValidateTokenAsync(string? token) { if (token is null) @@ -52,13 +60,18 @@ public class GitHubClientService(IOptions configuration, ILogger return new ClaimsPrincipal(identity); } - public async Task> GetAllTagsAsync() + public async Task> GetAllTagsAsync(string? dbMainTagName) { var config = configuration.Value; var credentials = new Credentials(config.OrgToken); var client = new GitHubClient(new ProductHeaderValue(config.UserAgent), new InMemoryCredentialStore(credentials)); - var releases = await client.Repository.Release.GetAll(config.OwnerOrg, config.Rubberduck, new ApiOptions { PageCount = 1, PageSize = 10 }); + + var getReleases = client.Repository.Release.GetAll(config.OwnerOrg, config.Rubberduck, new ApiOptions { PageCount = 1, PageSize = 10 }); + var getKnownMain = client.Repository.Release.Get(config.OwnerOrg, config.Rubberduck, dbMainTagName); + await Task.WhenAll(getReleases, getKnownMain); + + var releases = (await getReleases).Append(await getKnownMain).ToHashSet(new ReleaseComparer()); return (from release in releases let installer = release.Assets.SingleOrDefault(asset => asset.Name.EndsWith(".exe") && asset.Name.StartsWith("Rubberduck.Setup"))