chore: add csharpier to husky, format backend with csharpier

This commit is contained in:
sam 2024-10-02 00:28:07 +02:00
parent 5fab66444f
commit 7f971e8549
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
73 changed files with 2098 additions and 1048 deletions

View file

@ -17,7 +17,9 @@ public class AuthenticationMiddleware(DatabaseContext db) : IMiddleware
return;
}
if (!AuthUtils.TryParseToken(ctx.Request.Headers.Authorization.ToString(), out var rawToken))
if (
!AuthUtils.TryParseToken(ctx.Request.Headers.Authorization.ToString(), out var rawToken)
)
{
await next(ctx);
return;
@ -40,6 +42,7 @@ public static class HttpContextExtensions
private const string Key = "token";
public static void SetToken(this HttpContext ctx, Token token) => ctx.Items.Add(Key, token);
public static User? GetUser(this HttpContext ctx) => ctx.GetToken()?.User;
public static User GetUserOrThrow(this HttpContext ctx) =>
@ -54,4 +57,4 @@ public static class HttpContextExtensions
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class AuthenticateAttribute : Attribute;
public class AuthenticateAttribute : Attribute;

View file

@ -18,14 +18,26 @@ public class AuthorizationMiddleware : IMiddleware
var token = ctx.GetToken();
if (token == null)
throw new ApiError.Unauthorized("This endpoint requires an authenticated user.",
ErrorCode.AuthenticationRequired);
if (attribute.Scopes.Length > 0 && attribute.Scopes.Except(token.Scopes.ExpandScopes()).Any())
throw new ApiError.Forbidden("This endpoint requires ungranted scopes.",
attribute.Scopes.Except(token.Scopes.ExpandScopes()), ErrorCode.MissingScopes);
throw new ApiError.Unauthorized(
"This endpoint requires an authenticated user.",
ErrorCode.AuthenticationRequired
);
if (
attribute.Scopes.Length > 0
&& attribute.Scopes.Except(token.Scopes.ExpandScopes()).Any()
)
throw new ApiError.Forbidden(
"This endpoint requires ungranted scopes.",
attribute.Scopes.Except(token.Scopes.ExpandScopes()),
ErrorCode.MissingScopes
);
if (attribute.RequireAdmin && token.User.Role != UserRole.Admin)
throw new ApiError.Forbidden("This endpoint can only be used by admins.");
if (attribute.RequireModerator && token.User.Role != UserRole.Admin && token.User.Role != UserRole.Moderator)
if (
attribute.RequireModerator
&& token.User.Role != UserRole.Admin
&& token.User.Role != UserRole.Moderator
)
throw new ApiError.Forbidden("This endpoint can only be used by moderators.");
await next(ctx);
@ -39,4 +51,4 @@ public class AuthorizeAttribute(params string[] scopes) : Attribute
public readonly bool RequireModerator = scopes.Contains(":moderator");
public readonly string[] Scopes = scopes.Except([":admin", ":moderator"]).ToArray();
}
}

View file

@ -21,19 +21,26 @@ public class ErrorHandlerMiddleware(ILogger baseLogger, IHub sentry) : IMiddlewa
if (ctx.Response.HasStarted)
{
logger.Error(e, "Error in {ClassName} ({Path}) after response started being sent", typeName,
ctx.Request.Path);
logger.Error(
e,
"Error in {ClassName} ({Path}) after response started being sent",
typeName,
ctx.Request.Path
);
sentry.CaptureException(e, scope =>
{
var user = ctx.GetUser();
if (user != null)
scope.User = new SentryUser
{
Id = user.Id.ToString(),
Username = user.Username
};
});
sentry.CaptureException(
e,
scope =>
{
var user = ctx.GetUser();
if (user != null)
scope.User = new SentryUser
{
Id = user.Id.ToString(),
Username = user.Username,
};
}
);
return;
}
@ -45,13 +52,17 @@ public class ErrorHandlerMiddleware(ILogger baseLogger, IHub sentry) : IMiddlewa
ctx.Response.ContentType = "application/json; charset=utf-8";
if (ae is ApiError.Forbidden fe)
{
await ctx.Response.WriteAsync(JsonConvert.SerializeObject(new HttpApiError
{
Status = (int)fe.StatusCode,
Code = ErrorCode.Forbidden,
Message = fe.Message,
Scopes = fe.Scopes.Length > 0 ? fe.Scopes : null
}));
await ctx.Response.WriteAsync(
JsonConvert.SerializeObject(
new HttpApiError
{
Status = (int)fe.StatusCode,
Code = ErrorCode.Forbidden,
Message = fe.Message,
Scopes = fe.Scopes.Length > 0 ? fe.Scopes : null,
}
)
);
return;
}
@ -61,45 +72,61 @@ public class ErrorHandlerMiddleware(ILogger baseLogger, IHub sentry) : IMiddlewa
return;
}
await ctx.Response.WriteAsync(JsonConvert.SerializeObject(new HttpApiError
{
Status = (int)ae.StatusCode,
Code = ae.ErrorCode,
Message = ae.Message,
}));
await ctx.Response.WriteAsync(
JsonConvert.SerializeObject(
new HttpApiError
{
Status = (int)ae.StatusCode,
Code = ae.ErrorCode,
Message = ae.Message,
}
)
);
return;
}
if (e is FoxnounsError fce)
{
logger.Error(fce.Inner ?? fce, "Exception in {ClassName} ({Path})", typeName, ctx.Request.Path);
logger.Error(
fce.Inner ?? fce,
"Exception in {ClassName} ({Path})",
typeName,
ctx.Request.Path
);
}
else
{
logger.Error(e, "Exception in {ClassName} ({Path})", typeName, ctx.Request.Path);
}
var errorId = sentry.CaptureException(e, scope =>
{
var user = ctx.GetUser();
if (user != null)
scope.User = new SentryUser
{
Id = user.Id.ToString(),
Username = user.Username
};
});
var errorId = sentry.CaptureException(
e,
scope =>
{
var user = ctx.GetUser();
if (user != null)
scope.User = new SentryUser
{
Id = user.Id.ToString(),
Username = user.Username,
};
}
);
ctx.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
ctx.Response.Headers.RequestId = ctx.TraceIdentifier;
ctx.Response.ContentType = "application/json; charset=utf-8";
await ctx.Response.WriteAsync(JsonConvert.SerializeObject(new HttpApiError
{
Status = (int)HttpStatusCode.InternalServerError,
Code = ErrorCode.InternalServerError,
ErrorId = errorId.ToString(),
Message = "Internal server error",
}));
await ctx.Response.WriteAsync(
JsonConvert.SerializeObject(
new HttpApiError
{
Status = (int)HttpStatusCode.InternalServerError,
Code = ErrorCode.InternalServerError,
ErrorId = errorId.ToString(),
Message = "Internal server error",
}
)
);
}
}
}
@ -118,4 +145,4 @@ public record HttpApiError
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string[]? Scopes { get; init; }
}
}