From f5772efe25caf387240bb1f9307b22bbc2713de3 Mon Sep 17 00:00:00 2001 From: devlooped-bot Date: Sat, 29 Jun 2024 04:56:08 +0000 Subject: [PATCH] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Bump=20files=20with=20dotn?= =?UTF-8?q?et-file=20sync=20#=20devlooped/oss?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update to newest JsonWebTokens https://github.com/devlooped/oss/commit/068140b - Add support and showcase determining install time https://github.com/devlooped/oss/commit/717ddb1 - Fix formatting/whitespace https://github.com/devlooped/oss/commit/7febebc - Switch to built-in item metadata for manifest analyzer files https://github.com/devlooped/oss/commit/49c9a38 - Extend grace period to unknown status too https://github.com/devlooped/oss/commit/9f918ec - Change debug traces location to the well-known location of .sponsorlink https://github.com/devlooped/oss/commit/1019e2a - Remove unused tracing overloads https://github.com/devlooped/oss/commit/08a8488 - Fix roles checking from new identity-based token handler https://github.com/devlooped/oss/commit/6eecf46 --- .../Analyzer/StatusReportingAnalyzer.cs | 4 +-- src/SponsorLink/SponsorLink.targets | 4 +-- src/SponsorLink/SponsorLink/SponsorLink.cs | 9 +++-- .../SponsorLink/SponsorLinkAnalyzer.cs | 34 ++++++++++++++++++- src/SponsorLink/SponsorLink/Tracing.cs | 6 ---- src/SponsorLink/Tests/Sample.cs | 2 +- src/SponsorLink/Tests/SponsorableManifest.cs | 2 +- src/SponsorLink/Tests/Tests.csproj | 13 +++++-- 8 files changed, 56 insertions(+), 18 deletions(-) diff --git a/src/SponsorLink/Analyzer/StatusReportingAnalyzer.cs b/src/SponsorLink/Analyzer/StatusReportingAnalyzer.cs index 2c4a2530..9f024660 100644 --- a/src/SponsorLink/Analyzer/StatusReportingAnalyzer.cs +++ b/src/SponsorLink/Analyzer/StatusReportingAnalyzer.cs @@ -14,14 +14,14 @@ namespace Analyzer; public class StatusReportingAnalyzer : DiagnosticAnalyzer { public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(new DiagnosticDescriptor( - "SL001", "Report Sponsoring Status", "Reports sponsoring status determined by SponsorLink", "Sponsors", + "SL001", "Report Sponsoring Status", "Reports sponsoring status determined by SponsorLink", "Sponsors", DiagnosticSeverity.Warning, true)); public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); - + context.RegisterCompilationAction(c => { var installed = c.Options.AdditionalFiles.Where(x => diff --git a/src/SponsorLink/SponsorLink.targets b/src/SponsorLink/SponsorLink.targets index 2daf6126..17beed1d 100644 --- a/src/SponsorLink/SponsorLink.targets +++ b/src/SponsorLink/SponsorLink.targets @@ -16,8 +16,8 @@ $(Product) $([System.Text.RegularExpressions.Regex]::Replace("$(FundingProduct)", "[^A-Z]", "")) - - 21 + + 15 diff --git a/src/SponsorLink/SponsorLink/SponsorLink.cs b/src/SponsorLink/SponsorLink/SponsorLink.cs index 81032c6e..a4c06754 100644 --- a/src/SponsorLink/SponsorLink/SponsorLink.cs +++ b/src/SponsorLink/SponsorLink/SponsorLink.cs @@ -88,7 +88,7 @@ public static bool TryRead([NotNullWhen(true)] out ClaimsPrincipal? principal, I if (Validate(value.jwt, value.jwk, out var token, out var identity, false) == ManifestStatus.Valid && identity != null) { if (principal == null) - principal = new(identity); + principal = new JwtRolesPrincipal(identity); else principal.AddIdentity(identity); } @@ -158,7 +158,7 @@ public static ManifestStatus Validate(string jwt, string jwk, out SecurityToken? } token = result.SecurityToken; - identity = new ClaimsIdentity(result.ClaimsIdentity.Claims); + identity = new ClaimsIdentity(result.ClaimsIdentity.Claims, "JWT"); if (validateExpiration && token.ValidTo == DateTime.MinValue) return ManifestStatus.Invalid; @@ -169,4 +169,9 @@ public static ManifestStatus Validate(string jwt, string jwk, out SecurityToken? return ManifestStatus.Valid; } + + class JwtRolesPrincipal(ClaimsIdentity identity) : ClaimsPrincipal([identity]) + { + public override bool IsInRole(string role) => HasClaim("roles", role) || base.IsInRole(role); + } } diff --git a/src/SponsorLink/SponsorLink/SponsorLinkAnalyzer.cs b/src/SponsorLink/SponsorLink/SponsorLinkAnalyzer.cs index 9157e2fe..d87c238c 100644 --- a/src/SponsorLink/SponsorLink/SponsorLinkAnalyzer.cs +++ b/src/SponsorLink/SponsorLink/SponsorLinkAnalyzer.cs @@ -58,10 +58,10 @@ public override void Initialize(AnalysisContext context) // Setting the status early allows other analyzers to potentially check for it. var status = SetStatus(manifests); + // Never report any diagnostic unless we're in an editor. if (IsEditor) { - // NOTE: even if we don't report the diagnostic, we still set the status so other analyzers can use it. ctx.RegisterCompilationEndAction(ctx => { // NOTE: for multiple projects with the same product name, we only report one diagnostic, @@ -69,6 +69,38 @@ public override void Initialize(AnalysisContext context) // multiple diagnostics for each project in a solution that uses the same product. if (Diagnostics.Pop(Funding.Product) is Diagnostic diagnostic) { + // For unknown (never sync'ed), only report if install grace period is over + if (status == SponsorStatus.Unknown) + { + var noGrace = ctx.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue("build_property.SponsorLinkNoInstallGrace", out var value) && + bool.TryParse(value, out var skipCheck) && skipCheck; + + // NOTE: we'll always report if noGrace is set to true, regardless of install time, for + // testing purposes. This can be achieved via MSBuild with: + // + // true + // + // + // + // + if (noGrace == false) + { + var installed = ctx.Options.AdditionalFiles.Where(x => + { + var options = ctx.Options.AnalyzerConfigOptionsProvider.GetOptions(x); + // In release builds, we'll have a single such item, since we IL-merge the analyzer. + return options.TryGetValue("build_metadata.Analyzer.ItemType", out var itemType) && + options.TryGetValue("build_metadata.Analyzer.NuGetPackageId", out var packageId) && + itemType == "Analyzer" && + packageId == Funding.Product; + }).Select(x => File.GetLastWriteTime(x.Path)).OrderByDescending(x => x).FirstOrDefault(); + + // NOTE: if we can't determine install time, we'll always report. + if (installed != default && installed.AddDays(Funding.Grace) > DateTime.Now) + return; + } + } + ctx.ReportDiagnostic(diagnostic); } }); diff --git a/src/SponsorLink/SponsorLink/Tracing.cs b/src/SponsorLink/SponsorLink/Tracing.cs index 275a2ee4..ad5d9b35 100644 --- a/src/SponsorLink/SponsorLink/Tracing.cs +++ b/src/SponsorLink/SponsorLink/Tracing.cs @@ -10,12 +10,6 @@ namespace Devlooped.Sponsors; static class Tracing { - public static void Trace(string message, object? value, [CallerArgumentExpression("value")] string? expression = null, [CallerFilePath] string? filePath = null, [CallerLineNumber] int lineNumber = 0) - => Trace($"{message}: {value} ({expression})", filePath, lineNumber); - - public static void Trace(object? value, [CallerArgumentExpression("value")] string? expression = null, [CallerFilePath] string? filePath = null, [CallerLineNumber] int lineNumber = 0) - => Trace($"{value} ({expression})", filePath, lineNumber); - public static void Trace([CallerMemberName] string? message = null, [CallerFilePath] string? filePath = null, [CallerLineNumber] int lineNumber = 0) { var trace = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable("SPONSORLINK_TRACE")); diff --git a/src/SponsorLink/Tests/Sample.cs b/src/SponsorLink/Tests/Sample.cs index 897c91ce..6249e62a 100644 --- a/src/SponsorLink/Tests/Sample.cs +++ b/src/SponsorLink/Tests/Sample.cs @@ -40,7 +40,7 @@ public void Test(string culture, SponsorStatus kind) public void RenderSponsorables() { Assert.NotEmpty(SponsorLink.Sponsorables); - + foreach (var pair in SponsorLink.Sponsorables) { output.WriteLine($"{pair.Key} = {pair.Value}"); diff --git a/src/SponsorLink/Tests/SponsorableManifest.cs b/src/SponsorLink/Tests/SponsorableManifest.cs index 89af2425..d65d0fb7 100644 --- a/src/SponsorLink/Tests/SponsorableManifest.cs +++ b/src/SponsorLink/Tests/SponsorableManifest.cs @@ -285,7 +285,7 @@ public ClaimsIdentity Validate(string jwt, out SecurityToken? token) MapInboundClaims = false, SetDefaultTimesOnTokenCreation = false, }.ValidateTokenAsync(jwt, validation).Result; - + token = result.SecurityToken; return result.ClaimsIdentity; } diff --git a/src/SponsorLink/Tests/Tests.csproj b/src/SponsorLink/Tests/Tests.csproj index 1cf4c501..1f5dd372 100644 --- a/src/SponsorLink/Tests/Tests.csproj +++ b/src/SponsorLink/Tests/Tests.csproj @@ -19,7 +19,7 @@ - + @@ -54,8 +54,15 @@ - - + + + + + true + + + + \ No newline at end of file