Files
RenewCMS/internal/infrastructure/useCases/auditFailures.go
T

107 lines
4.1 KiB
Go

package useCases
import (
"RenewCMS/internal/domain/article"
"RenewCMS/internal/domain/audit"
"RenewCMS/internal/domain/image"
"RenewCMS/internal/domain/invite"
"RenewCMS/internal/domain/purge"
"RenewCMS/internal/domain/update"
"RenewCMS/internal/domain/user"
"context"
"errors"
"slices"
)
const GenericFailureReason = "Something went wrong on our side. Please try again."
type failureReason struct {
cause error
reason string
}
var failureReasons = []failureReason{
{article.ErrInvalidTitle, "The title must be between 3 and 200 characters."},
{image.ErrImageTypeNotAllowed, "The file must be a PNG, JPEG, WEBP or SVG image."},
{image.ErrImageTooLarge, "The file is too large to upload."},
{image.ErrImageUnreadable, "The image could not be read."},
{image.ErrInvalidFilename, "That file name is not valid."},
{image.ErrInvalidMergeRequest, "The merge request is not valid."},
{image.ErrMergeCopyMissing, "One of the copies no longer exists."},
{image.ErrMergeHashMismatch, "The images are not identical copies."},
{image.ErrSourceTooLarge, "The source image is too large to generate this variant."},
{image.ErrVariantSourceUnsupported, "Variants aren't generated for this format."},
{image.ErrVariantSourceUnreadable, "The source image can't be read, so this variant can't be generated."},
{image.ErrVariantExists, "A variant with that name already exists."},
{purge.ErrPurgeConflict, "The library changed since the preview. Review it again."},
{purge.ErrPurgeBusy, "A purge is already running."},
{user.ErrRegistrationClosed, "Registration is closed on this site."},
{user.ErrVerificationEmailNotSent, "The verification email could not be sent."},
{user.ErrInvalidVerificationCode, "The verification code is not valid."},
{user.ErrVerificationCodeExpired, "The verification code has expired."},
{user.ErrInvalidDisplayName, "That display name is too long."},
{user.ErrUsernameTaken, "That username is already taken."},
{invite.ErrEmailHasAccount, "That email already has an account."},
{invite.ErrPendingInvite, "An invitation is already pending for that email."},
{invite.ErrInviteEmailNotSent, "The invitation email could not be sent."},
{invite.ErrInviteAlreadyAccepted, "That invitation was already accepted."},
{invite.ErrInviteInvalid, "That invitation is not valid."},
{invite.ErrInviteExpired, "That invitation has expired."},
{update.ErrFeedUnavailable, "The release feed could not be reached."},
{update.ErrNoRelease, "No release was found."},
{update.ErrNotPrepared, "This server cannot apply updates."},
{update.ErrJobInProgress, "An update is already being downloaded."},
{update.ErrRestartPending, "A restart is already pending."},
{update.ErrNothingToUpdate, "There is nothing to update."},
{update.ErrPreflightRefused, "The update cannot be downloaded."},
{update.ErrRestartKindMismatch, "The requested restart does not match the server state."},
}
var restartFailureReasons = []failureReason{
{update.ErrJobInProgress, "An update is still being downloaded."},
}
var downloadFailureReasons = map[string]string{
update.ErrorKindDownload: "The update could not be downloaded.",
update.ErrorKindVerification: "The downloaded update failed its integrity check.",
}
var notFoundCauses = []error{
article.ErrArticleNotFound,
image.ErrImageNotFound,
image.ErrVariantNotFound,
invite.ErrInviteNotFound,
user.ErrUserNotFound,
}
func reasonFor(err error, overrides ...failureReason) string {
for _, candidate := range slices.Concat(overrides, failureReasons) {
if errors.Is(err, candidate.cause) {
return candidate.reason
}
}
return GenericFailureReason
}
func isNotFound(err error) bool {
for _, cause := range notFoundCauses {
if errors.Is(err, cause) {
return true
}
}
return false
}
func recordFailure(ctx context.Context, recorder audit.Recorder, event audit.Event, err error, overrides ...failureReason) {
if isNotFound(err) {
return
}
failFrom(ctx, recorder, event, reasonFor(err, overrides...))
}
func failFrom(ctx context.Context, recorder audit.Recorder, event audit.Event, reason string) {
event.Outcome = audit.OutcomeFailed
event.FailureReason = &reason
recorder.Record(ctx, event)
}