feat: activity log producers
This commit is contained in:
1 parent
50b1649965
commit
e37a46a027
93 files changed
+3396
-440
No files matched your search
@@ -0,0 +1,101 @@
|
||||
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."},
|
||||
{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,
|
||||
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)
|
||||
}
|
||||
Reference in new issue
Block a user