Adds JetBrains.Annotations to reduce amount of false positives by static code analysis

This commit is contained in:
Jonathan Bourdon
2024-08-07 03:29:59 -04:00
parent f3b225d3a8
commit 7baf1146ac
42 changed files with 118 additions and 119 deletions

View File

@@ -2,7 +2,7 @@
/// <summary>
/// Adapted from https://raw.githubusercontent.com/uuidjs/uuid/main/src/v7.ts.
/// to match the uuidv7 generated on the client
/// to match the uuid v7 generated on the client
/// </summary>
public static class GuidHelper
{
@@ -27,14 +27,14 @@ public static class GuidHelper
var values = V7Bytes(randomValues, State.Msecs, State.Seq);
return new(values);
return new Guid(values);
}
private static void UpdateV7State(V7State state, long now, byte[] rnds)
private static void UpdateV7State(V7State state, long now, byte[] randomBytes)
{
if (now > state.Msecs)
{
state.Seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9];
state.Seq = (randomBytes[6] << 23) | (randomBytes[7] << 16) | (randomBytes[8] << 8) | randomBytes[9];
state.Msecs = now;
}
else
@@ -47,7 +47,7 @@ public static class GuidHelper
}
}
private static byte[] V7Bytes(byte[] rnds, long? msecs = null, int? seq = null, byte[] buf = null, int offset = 0)
private static byte[] V7Bytes(byte[] randomBytes, long? msecs = null, int? seq = null, byte[]? buf = null, int offset = 0)
{
if (buf == null)
{
@@ -57,7 +57,7 @@ public static class GuidHelper
// Defaults
msecs ??= DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
seq ??= ((rnds[6] & 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9];
seq ??= ((randomBytes[6] & 0x7f) << 24) | (randomBytes[7] << 16) | (randomBytes[8] << 8) | randomBytes[9];
// byte 0-5: timestamp (48 bits)
buf[offset++] = (byte)((msecs.Value / 0x10000000000) & 0xff);
@@ -80,14 +80,14 @@ public static class GuidHelper
buf[offset++] = (byte)((seq.Value >> 6) & 0xff);
// byte 10: sequence bits 0-5 (6 bits) | random (2 bits)
buf[offset++] = (byte)(((seq.Value << 2) & 0xff) | (rnds[10] & 0x03));
buf[offset++] = (byte)(((seq.Value << 2) & 0xff) | (randomBytes[10] & 0x03));
// bytes 11-15: random (40 bits)
buf[offset++] = rnds[11];
buf[offset++] = rnds[12];
buf[offset++] = rnds[13];
buf[offset++] = rnds[14];
buf[offset++] = rnds[15];
buf[offset++] = randomBytes[11];
buf[offset++] = randomBytes[12];
buf[offset++] = randomBytes[13];
buf[offset++] = randomBytes[14];
buf[offset] = randomBytes[15];
return buf;
}

View File

@@ -1,3 +1,5 @@
namespace Hutopy.Web.Common;
public class MissingClaimException(string claimName) : Exception;
public class MissingClaimException(
string claimName)
: Exception;

View File

@@ -10,7 +10,7 @@ namespace Hutopy.Web.Controllers;
public class FacebookController(IIdentityService identityService) : Controller
{
[HttpGet("/api/facebook/sign-in")]
[Microsoft.AspNetCore.Mvc.HttpGet("/api/facebook/sign-in")]
public async Task SignIn()
{
await HttpContext.ChallengeAsync(FacebookDefaults.AuthenticationScheme,

View File

@@ -16,8 +16,8 @@ public class GoogleController(
IOptionsSnapshot<JwtOptions> jwtOptions)
: Controller
{
[HttpPost("/api/google/sign-in")]
public async Task<IActionResult> SignIn([FromBody] GoogleSignInRequest request)
[Microsoft.AspNetCore.Mvc.HttpPost("/api/google/sign-in")]
public async Task<IActionResult> SignIn([Microsoft.AspNetCore.Mvc.FromBody] GoogleSignInRequest request)
{
using var httpClient = httpClientFactory.CreateClient();

View File

@@ -2,6 +2,7 @@
using Azure.Identity;
using Hutopy.Application.Common.Interfaces;
using Hutopy.Infrastructure.Data;
using Hutopy.Web.Infrastructure;
using Hutopy.Web.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.Facebook;

View File

@@ -1,4 +1,5 @@
using Hutopy.Application.Users.Queries.GetCurrentUser;
using Hutopy.Web.Infrastructure;
namespace Hutopy.Web.Endpoints;

View File

@@ -1,6 +1,7 @@
using Hutopy.Application.Common.Models;
using Hutopy.Application.FutureCreators.Commands;
using Hutopy.Application.FutureCreators.Queries;
using Hutopy.Web.Infrastructure;
namespace Hutopy.Web.Endpoints;

View File

@@ -1,5 +1,6 @@
using Hutopy.Application.Stripe.Commands;
using Hutopy.Application.Stripe.Queries;
using Hutopy.Web.Infrastructure;
namespace Hutopy.Web.Endpoints;

View File

@@ -1,4 +1,5 @@
using Hutopy.Application.Users.Commands;
using Hutopy.Web.Infrastructure;
namespace Hutopy.Web.Endpoints;

View File

@@ -1,5 +1,6 @@
using Hutopy.Application.Users.Commands;
using Hutopy.Application.Users.Queries.GetUser;
using Hutopy.Web.Infrastructure;
namespace Hutopy.Web.Endpoints;

View File

@@ -1,6 +1,4 @@
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Contents.Data;
namespace Hutopy.Web.Features.Contents.Data;
public class ContentDbContext(
DbContextOptions<ContentDbContext> options)

View File

@@ -1,5 +1,4 @@
using Hutopy.Web.Features.Contents.Data;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Contents;

View File

@@ -1,14 +1,14 @@
using FastEndpoints;
using Hutopy.Web.Features.Contents.Data;
using Microsoft.EntityFrameworkCore;
using Hutopy.Web.Features.Contents.Data;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public record ChangeAboutRequest(
Guid CreatorId,
string? Title,
string? Description);
[PublicAPI]
public class ChangeAboutHandler(
ContentDbContext context)
: Endpoint<ChangeAboutRequest>

View File

@@ -1,17 +1,16 @@
using FastEndpoints;
using Hutopy.Application.AzureBlobStorage.Constants;
using Hutopy.Application.AzureBlobStorage.Constants;
using Hutopy.Application.Common.Interfaces;
using Hutopy.Web.Features.Contents.Data;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public record ChangeBannerRequest(
Guid CreatorId,
IFormFile File);
[PublicAPI]
public class ChangeBannerHandler(
IHttpContextAccessor contextAccessor,
ContentDbContext context,
IBlobStorage blobStorage)
: Endpoint<ChangeBannerRequest>
@@ -22,7 +21,7 @@ public class ChangeBannerHandler(
Options(o => o.WithTags("Contents"));
AllowFileUploads();
}
public override async Task HandleAsync(ChangeBannerRequest request, CancellationToken ct)
{
var creator = await context
@@ -37,7 +36,7 @@ public class ChangeBannerHandler(
await SendNotFoundAsync(ct);
return;
}
// TODO: this upload should be done to the Creators container
var blobUrl = await blobStorage.UploadFileAsync(
ContainerNames.Users,
@@ -45,11 +44,11 @@ public class ChangeBannerHandler(
request.File.OpenReadStream(),
request.File.ContentType,
ct);
creator.Images.Banner = blobUrl;
await context.SaveChangesAsync(ct);
await SendOkAsync(blobUrl, ct);
}
}

View File

@@ -1,10 +1,8 @@
using FastEndpoints;
using FluentValidation;
using Hutopy.Web.Features.Contents.Data;
using Microsoft.EntityFrameworkCore;
using Hutopy.Web.Features.Contents.Data;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public record ChangeColorsRequest(
Guid CreatorId,
string? BannerTop,
@@ -12,7 +10,8 @@ public record ChangeColorsRequest(
string? Accent,
string? Menu);
public sealed class ChangeColorsRequestValidator
[PublicAPI]
public sealed class ChangeColorsRequestValidator
: Validator<ChangeColorsRequest>
{
public ChangeColorsRequestValidator()

View File

@@ -1,17 +1,16 @@
using FastEndpoints;
using Hutopy.Application.AzureBlobStorage.Constants;
using Hutopy.Application.AzureBlobStorage.Constants;
using Hutopy.Application.Common.Interfaces;
using Hutopy.Web.Features.Contents.Data;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public record ChangeLogoRequest(
Guid CreatorId,
IFormFile File);
[PublicAPI]
public class ChangeLogoHandler(
IHttpContextAccessor contextAccessor,
ContentDbContext context,
IBlobStorage blobStorage)
: Endpoint<ChangeLogoRequest>
@@ -22,7 +21,7 @@ public class ChangeLogoHandler(
Options(o => o.WithTags("Contents"));
AllowFileUploads();
}
public override async Task HandleAsync(ChangeLogoRequest request, CancellationToken ct)
{
var creator = await context
@@ -37,7 +36,7 @@ public class ChangeLogoHandler(
await SendNotFoundAsync(ct);
return;
}
// TODO: this upload should be done to the Creators container
var blobUrl = await blobStorage.UploadFileAsync(
ContainerNames.Users,
@@ -45,11 +44,11 @@ public class ChangeLogoHandler(
request.File.OpenReadStream(),
request.File.ContentType,
ct);
creator.Images.Logo = blobUrl;
await context.SaveChangesAsync(ct);
await SendOkAsync(blobUrl, ct);
}
}

View File

@@ -1,9 +1,8 @@
using FastEndpoints;
using Hutopy.Web.Features.Contents.Data;
using Microsoft.EntityFrameworkCore;
using Hutopy.Web.Features.Contents.Data;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public record ChangeSocialsRequest(
Guid CreatorId,
string? FacebookUrl,
@@ -15,6 +14,7 @@ public record ChangeSocialsRequest(
string? RedditUrl,
string? WebsiteUrl);
[PublicAPI]
public class ChangeSocialsHandler(
ContentDbContext context)
: Endpoint<ChangeSocialsRequest>

View File

@@ -1,6 +1,4 @@
using System.Collections.Concurrent;
using FastEndpoints;
using FluentValidation;
using Hutopy.Application.AzureBlobStorage.Constants;
using Hutopy.Application.Common.Interfaces;
using Hutopy.Web.Common;
@@ -8,6 +6,7 @@ using Hutopy.Web.Features.Contents.Data;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public record PostContentRequest(
Guid Id,
Guid CreatorId,
@@ -15,6 +14,7 @@ public record PostContentRequest(
string Description,
IFormFileCollection Files);
[PublicAPI]
public sealed class PostContentRequestValidator : Validator<PostContentRequest>
{
public PostContentRequestValidator()

View File

@@ -1,14 +1,14 @@
using FastEndpoints;
using FluentValidation;
using Hutopy.Web.Common;
using Hutopy.Web.Common;
using Hutopy.Web.Features.Contents.Data;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public record CreateCreatorRequest(
Guid CreatorId,
string Name);
[UsedImplicitly]
public sealed class CreateCreatorRequestValidator : Validator<CreateCreatorRequest>
{
public CreateCreatorRequestValidator()
@@ -23,6 +23,7 @@ public sealed class CreateCreatorRequestValidator : Validator<CreateCreatorReque
}
}
[PublicAPI]
public sealed class CreateCreatorHandler(
ContentDbContext context)
: Endpoint<CreateCreatorRequest>

View File

@@ -1,14 +1,14 @@
using FastEndpoints;
using Hutopy.Web.Features.Contents.Data;
using Microsoft.EntityFrameworkCore;
using Hutopy.Web.Features.Contents.Data;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public sealed class GetContentRequest
{
public Guid ContentId { get; set; }
}
[PublicAPI]
public class GetContent(
ContentDbContext context)
: Endpoint<GetContentRequest, Content>

View File

@@ -1,11 +1,9 @@
using System.Linq.Expressions;
using FastEndpoints;
using Hutopy.Web.Features.Contents.Data;
using Hutopy.Web.Features.Contents.Data;
using Hutopy.Web.Features.Contents.Handlers.Models;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public sealed class GetContentsByCreatorRequest
{
public Guid UserId { get; set; }
@@ -13,6 +11,7 @@ public sealed class GetContentsByCreatorRequest
[BindFrom("last_id")] public Guid? LastId { get; set; }
}
[PublicAPI]
public class GetContentsByCreatorHandler(
ContentDbContext context)
: Endpoint<GetContentsByCreatorRequest, List<ContentModel>>

View File

@@ -1,16 +1,15 @@
using FastEndpoints;
using FluentValidation;
using Hutopy.Web.Features.Contents.Data;
using Hutopy.Web.Features.Contents.Data;
using Hutopy.Web.Features.Contents.Handlers.Models;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public sealed class GetCreatorByAliasRequest
{
public required string Name { get; set; }
}
[UsedImplicitly]
public sealed class GetCreatorByAliasRequestValidator
: Validator<GetCreatorByAliasRequest>
{
@@ -22,6 +21,7 @@ public sealed class GetCreatorByAliasRequestValidator
}
}
[PublicAPI]
public class GetCreatorByAliasHandler(
ContentDbContext context)
: Endpoint<GetCreatorByAliasRequest, CreatorModel>
@@ -54,18 +54,16 @@ public class GetCreatorByAliasHandler(
s => s.CreatorId == creator.Id,
cancellationToken: ct);
var model = new CreatorModel
{
Id = creator.Id,
CreatedBy = creator.CreatedBy,
CreatedAt = creator.CreatedAt,
Name = creator.Name,
About = creator.About,
Socials = creator.Socials,
Colors = creator.Colors,
Images = creator.Images,
SubscriberCount = subscriberCount,
};
var model = new CreatorModel(
creator.Id,
creator.CreatedBy,
creator.CreatedAt,
creator.Name,
creator.About,
creator.Socials,
creator.Colors,
creator.Images,
subscriberCount);
await SendAsync(model, cancellation: ct);
}

View File

@@ -1,14 +1,14 @@
using FastEndpoints;
using FluentValidation;
using Hutopy.Web.Features.Contents.Data;
using Hutopy.Web.Features.Contents.Data;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public sealed class GetCreatorByIdRequest
{
public required Guid CreatorId { get; set; }
}
[UsedImplicitly]
public sealed class GetCreatorByIdRequestValidator
: Validator<GetCreatorByIdRequest>
{
@@ -20,6 +20,7 @@ public sealed class GetCreatorByIdRequestValidator
}
}
[PublicAPI]
public class GetCreatorByIdHandler(
ContentDbContext context)
: Endpoint<GetCreatorByIdRequest, Creator>

View File

@@ -1,11 +1,10 @@
using FastEndpoints;
using Hutopy.Web.Common;
using Hutopy.Web.Common;
using Hutopy.Web.Features.Contents.Data;
using Hutopy.Web.Features.Contents.Handlers.Models;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public class GetSubscriptionsHandler(
ContentDbContext context)
: EndpointWithoutRequest<List<SubscriptionModel>>
@@ -25,7 +24,7 @@ public class GetSubscriptionsHandler(
.Subscriptions
.Where(s => s.CreatedBy == userId)
.Select(s => new SubscriptionModel(
s.CreatorId,
s.CreatorId,
s.Creator!.Name,
s.Creator.Images.Logo))
.ToListAsync(cancellationToken: ct);

View File

@@ -2,6 +2,7 @@
namespace Hutopy.Web.Features.Contents.Handlers.Models;
[PublicAPI]
public record struct ContentModel(
Guid Id,
Guid CreatedBy,

View File

@@ -2,15 +2,14 @@
namespace Hutopy.Web.Features.Contents.Handlers.Models;
public class CreatorModel
{
public Guid Id { get; set; }
public Guid CreatedBy { get; set; }
public DateTimeOffset CreatedAt { get; set; }
public string Name { get; set; }
public About About { get; set; }
public Socials Socials { get; set; }
public Colors Colors { get; set; }
public Images Images { get; set; }
public int SubscriberCount { get; set; }
}
[PublicAPI]
public record struct CreatorModel(
Guid Id,
Guid CreatedBy,
DateTimeOffset CreatedAt,
string Name,
About About,
Socials Socials,
Colors Colors,
Images Images,
int SubscriberCount);

View File

@@ -1,5 +1,6 @@
namespace Hutopy.Web.Features.Contents.Handlers.Models;
[PublicAPI]
public record SubscriptionModel(
Guid CreatorId,
string CreatorName,

View File

@@ -1,16 +1,16 @@
using FastEndpoints;
using Hutopy.Web.Common;
using Hutopy.Web.Common;
using Hutopy.Web.Features.Contents.Data;
using Hutopy.Web.Features.Contents.Handlers.Models;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public sealed class SubscribeToCreatorRequest
{
public Guid CreatorId { get; set; }
}
[PublicAPI]
public sealed class SubscribeToCreatorHandler(
ContentDbContext context)
: Endpoint<SubscribeToCreatorRequest, SubscriptionModel>

View File

@@ -1,14 +1,15 @@
using FastEndpoints;
using Hutopy.Web.Common;
using Hutopy.Web.Common;
using Hutopy.Web.Features.Contents.Data;
namespace Hutopy.Web.Features.Contents.Handlers;
[PublicAPI]
public sealed class UnsubscribeFromCreatorRequest
{
public Guid CreatorId { get; set; }
}
[PublicAPI]
public class UnsubscribeFromCreatorHandler(
ContentDbContext context)
: Endpoint<UnsubscribeFromCreatorRequest>

View File

@@ -1,5 +1,4 @@
using Hutopy.Web.Features.Messages.Handlers.Models;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Messages.Data;

View File

@@ -1,5 +1,4 @@
using Hutopy.Web.Features.Messages.Data;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Messages;

View File

@@ -1,6 +1,4 @@
using FastEndpoints;
using FluentValidation;
using Hutopy.Web.Common;
using Hutopy.Web.Common;
using Hutopy.Web.Features.Messages.Data;
namespace Hutopy.Web.Features.Messages.Handlers;

View File

@@ -1,6 +1,4 @@
using FastEndpoints;
using FluentValidation;
using Hutopy.Web.Common;
using Hutopy.Web.Common;
using Hutopy.Web.Features.Messages.Data;
namespace Hutopy.Web.Features.Messages.Handlers;

View File

@@ -1,5 +1,4 @@
using FastEndpoints;
using Hutopy.Web.Features.Messages.Data;
using Hutopy.Web.Features.Messages.Data;
using Hutopy.Web.Features.Messages.Handlers.Models;
namespace Hutopy.Web.Features.Messages.Handlers;

View File

@@ -1,7 +1,5 @@
using FastEndpoints;
using Hutopy.Web.Features.Messages.Data;
using Hutopy.Web.Features.Messages.Data;
using Hutopy.Web.Features.Messages.Handlers.Models;
using Microsoft.EntityFrameworkCore;
namespace Hutopy.Web.Features.Messages.Handlers;

View File

@@ -1,5 +1,4 @@
using FastEndpoints;
using Hutopy.Web.Features.Messages.Data;
using Hutopy.Web.Features.Messages.Data;
using Hutopy.Web.Features.Messages.Handlers.Models;
namespace Hutopy.Web.Features.Messages.Handlers;

View File

@@ -1,3 +1,6 @@
global using Ardalis.GuardClauses;
global using Hutopy.Web.Infrastructure;
global using FastEndpoints;
global using FluentValidation;
global using JetBrains.Annotations;
global using MediatR;
global using Microsoft.EntityFrameworkCore;

View File

@@ -1,6 +1,8 @@
using Hutopy.Application.Common.Exceptions;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using ProblemDetails = Microsoft.AspNetCore.Mvc.ProblemDetails;
using ValidationException = Hutopy.Application.Common.Exceptions.ValidationException;
namespace Hutopy.Web.Infrastructure;

View File

@@ -1,5 +1,6 @@
@using Hutopy.Infrastructure.Identity
@using Microsoft.AspNetCore.Identity
@using Microsoft.AspNetCore.Mvc.TagHelpers
@inject SignInManager<ApplicationUser> SignInManager
@{

View File

@@ -1,5 +1,4 @@
using Azure.Identity;
using FastEndpoints;
using Hutopy.Application;
using Hutopy.Infrastructure;
using Hutopy.Infrastructure.Data;
@@ -9,8 +8,8 @@ using Hutopy.Web.Features.Contents;
using Hutopy.Web.Features.Contents.Data;
using Hutopy.Web.Features.Messages;
using Hutopy.Web.Features.Messages.Data;
using Hutopy.Web.Infrastructure;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.EntityFrameworkCore;
using NSwag;
using NSwag.Generation.AspNetCore.Processors;
using NSwag.Generation.Processors.Security;

View File

@@ -16,6 +16,7 @@
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" />
<PackageReference Include="Azure.Identity" />
<PackageReference Include="FastEndpoints" />
<PackageReference Include="JetBrains.Annotations" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Facebook" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Google" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" />