Skip to content

Commit

Permalink
Remove validation filter
Browse files Browse the repository at this point in the history
  • Loading branch information
xilapa committed Nov 2, 2023
1 parent 870ec82 commit 1145a27
Show file tree
Hide file tree
Showing 42 changed files with 392 additions and 346 deletions.
17 changes: 10 additions & 7 deletions src/Application/Alerts/Commands/CreateAlert/CreateAlertCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Mediator;
using FluentValidation;
using SiteWatcher.Application.Common.Command;
using SiteWatcher.Application.Common.Results;
using SiteWatcher.Application.Interfaces;
using SiteWatcher.Common.Services;
using SiteWatcher.Domain.Alerts;
Expand All @@ -8,7 +10,7 @@

namespace SiteWatcher.Application.Alerts.Commands.CreateAlert;

public class CreateAlertCommand : ICommand<DetailedAlertView>
public sealed class CreateAlertCommand
{
public string Name { get; set; } = null!;
public Frequencies Frequency { get; set; }
Expand All @@ -34,24 +36,25 @@ public static implicit operator CreateAlertInput(CreateAlertCommand command) =>
command.RegexPattern);
}

public class CreateAlertCommandHandler : ICommandHandler<CreateAlertCommand, DetailedAlertView>
public sealed class CreateAlertCommandHandler : BaseHandler<CreateAlertCommand, Result<DetailedAlertView>>
{
private readonly ISession _session;
private readonly ISiteWatcherContext _context;
private readonly IIdHasher _idHasher;

public CreateAlertCommandHandler(ISession session, ISiteWatcherContext context, IIdHasher idHasher)
public CreateAlertCommandHandler(ISession session, ISiteWatcherContext context, IIdHasher idHasher,
IValidator<CreateAlertCommand> validator) : base(validator)
{
_session = session;
_context = context;
_idHasher = idHasher;
}

public async ValueTask<DetailedAlertView> Handle(CreateAlertCommand request, CancellationToken cancellationToken)
protected override async Task<Result<DetailedAlertView>> HandleCommand(CreateAlertCommand command, CancellationToken ct)
{
var alert = AlertFactory.Create(request, _session.UserId!.Value, _session.Now);
var alert = AlertFactory.Create(command, _session.UserId!.Value, _session.Now);
_context.Alerts.Add(alert);
await _context.SaveChangesAsync(cancellationToken);
await _context.SaveChangesAsync(ct);
return DetailedAlertView.FromAlert(alert, _idHasher);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
using Mediator;
using Microsoft.EntityFrameworkCore;
using SiteWatcher.Application.Common.Commands;
using SiteWatcher.Application.Common.Command;
using SiteWatcher.Application.Common.Constants;
using SiteWatcher.Application.Common.Results;
using SiteWatcher.Application.Interfaces;
using SiteWatcher.Common.Services;
using SiteWatcher.Domain.Alerts.Events;
using SiteWatcher.Domain.Authentication;
using SiteWatcher.Domain.Common.Errors;
using SiteWatcher.Domain.Common.ValueObjects;

namespace SiteWatcher.Application.Alerts.Commands.DeleteAlert;

public class DeleteAlertCommand : ICommand<CommandResult>
public class DeleteAlertCommand
{
public string? AlertId { get; set; }
}

public class DeleteAlertCommandHandler : ICommandHandler<DeleteAlertCommand, CommandResult>
public class DeleteAlertCommandHandler : IApplicationHandler
{
private readonly ISiteWatcherContext _context;
private readonly IIdHasher _idHasher;
Expand All @@ -31,7 +33,7 @@ public DeleteAlertCommandHandler(ISiteWatcherContext context, IIdHasher idHasher
_mediator = mediator;
}

public async ValueTask<CommandResult> Handle(DeleteAlertCommand request, CancellationToken cancellationToken)
public async Task<Result> Handle(DeleteAlertCommand request, CancellationToken cancellationToken)
{
if(request.AlertId == null)
return ReturnError();
Expand All @@ -49,9 +51,9 @@ public async ValueTask<CommandResult> Handle(DeleteAlertCommand request, Cancell
if (deleted != 0)
await _mediator.Publish(new AlertsChangedEvent(_session.UserId!.Value), CancellationToken.None);

return deleted != 0 ? CommandResult.Empty() : ReturnError();
return deleted != 0 ? Result.Empty : ReturnError();
}

private static CommandResult ReturnError() =>
CommandResult.FromError(ApplicationErrors.ValueIsInvalid(nameof(DeleteAlertCommand.AlertId)));
private static Error ReturnError() =>
Error.Validation(ApplicationErrors.ValueIsInvalid(nameof(DeleteAlertCommand.AlertId)));
}
25 changes: 14 additions & 11 deletions src/Application/Alerts/Commands/UpdateAlert/UpdateAlertCommmand.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
using Mediator;
using SiteWatcher.Application.Common.Commands;
using FluentValidation;
using SiteWatcher.Application.Common.Command;
using SiteWatcher.Application.Common.Constants;
using SiteWatcher.Application.Common.Extensions;
using SiteWatcher.Application.Common.Results;
using SiteWatcher.Application.Interfaces;
using SiteWatcher.Common.Services;
using SiteWatcher.Domain.Alerts.DTOs;
using SiteWatcher.Domain.Alerts.Enums;
using SiteWatcher.Domain.Authentication;
using SiteWatcher.Domain.Common.DTOs;
using SiteWatcher.Domain.Common.Errors;
using SiteWatcher.Domain.Common.ValueObjects;

namespace SiteWatcher.Application.Alerts.Commands.UpdateAlert;

public class UpdateAlertCommmand : ICommand<CommandResult>
public class UpdateAlertCommmand
{
public string AlertId { get; set; } = null!;
public UpdateInfo<string>? Name { get; set; }
Expand Down Expand Up @@ -45,32 +47,33 @@ public UpdateAlertInput ToUpdateAlertInput(IIdHasher idHasher)
}
}

public class UpdateAlertCommandHandler : ICommandHandler<UpdateAlertCommmand, CommandResult>
public class UpdateAlertCommandHandler : BaseHandler<UpdateAlertCommmand, Result<DetailedAlertView>>
{
private readonly IIdHasher _idHasher;
private readonly ISiteWatcherContext _context;
private readonly ISession _session;

public UpdateAlertCommandHandler(IIdHasher idHasher, ISiteWatcherContext context, ISession session)
public UpdateAlertCommandHandler(IIdHasher idHasher, ISiteWatcherContext context, ISession session,
IValidator<UpdateAlertCommmand> validator) : base(validator)
{
_idHasher = idHasher;
_context = context;
_session = session;
}

public async ValueTask<CommandResult> Handle(UpdateAlertCommmand request, CancellationToken cancellationToken)
protected override async Task<Result<DetailedAlertView>> HandleCommand(UpdateAlertCommmand command, CancellationToken ct)
{
var updateInfo = request.ToUpdateAlertInput(_idHasher);
var updateInfo = command.ToUpdateAlertInput(_idHasher);

if (AlertId.Empty.Equals(updateInfo.AlertId) || updateInfo.AlertId.Value == 0)
return CommandResult.FromError(ApplicationErrors.ValueIsInvalid(nameof(UpdateAlertCommmand.AlertId)));
return Error.Validation(ApplicationErrors.ValueIsInvalid(nameof(UpdateAlertCommmand.AlertId)));

var alert = await _context.GetAlertForUpdateAsync(updateInfo.AlertId, _session.UserId!.Value, cancellationToken);
if (alert is null) return CommandResult.FromError(ApplicationErrors.ALERT_DO_NOT_EXIST);
var alert = await _context.GetAlertForUpdateAsync(updateInfo.AlertId, _session.UserId!.Value, ct);
if (alert is null) return Error.Validation(ApplicationErrors.ALERT_DO_NOT_EXIST);

alert.Update(updateInfo, _session.Now);
await _context.SaveChangesAsync(CancellationToken.None);

return CommandResult.FromValue(DetailedAlertView.FromAlert(alert, _idHasher));
return DetailedAlertView.FromAlert(alert, _idHasher);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Application.Alerts.Dtos;
using Dapper;
using Mediator;
using SiteWatcher.Application.Common.Commands;
using SiteWatcher.Application.Common.Command;
using SiteWatcher.Application.Common.Queries;
using SiteWatcher.Application.Common.Results;
using SiteWatcher.Application.Interfaces;
using SiteWatcher.Common.Services;
using SiteWatcher.Domain.Alerts.DTOs;
Expand All @@ -13,7 +13,7 @@

namespace SiteWatcher.Application.Alerts.Commands.GetUserAlerts;

public class GetUserAlertsQuery : IQuery<CommandResult>, ICacheable
public class GetUserAlertsQuery : ICacheable
{
public string? LastAlertId { get; set; }
public int Take { get; set; } = 10;
Expand All @@ -27,7 +27,7 @@ public string GetKey(ISession session) =>
public TimeSpan Expiration => TimeSpan.FromMinutes(60);
}

public class GetUserAlertsQueryHandler : IQueryHandler<GetUserAlertsQuery, CommandResult>
public class GetUserAlertsQueryHandler : IApplicationHandler
{
private readonly IIdHasher _idHasher;
private readonly ISession _session;
Expand All @@ -42,10 +42,10 @@ public GetUserAlertsQueryHandler(IIdHasher idHasher, ISession session, IDapperCo
_queries = queries;
}

public async ValueTask<CommandResult> Handle(GetUserAlertsQuery request, CancellationToken cancellationToken)
public async Task<Result<PaginatedList<SimpleAlertView>>> Handle(GetUserAlertsQuery request, CancellationToken cancellationToken)
{
if (request.Take == 0)
return CommandResult.Empty();
return Result<PaginatedList<SimpleAlertView>>.Empty;

var take = request.Take > 50 ? 50 : request.Take;
var lastAlertId = _idHasher.DecodeId(request.LastAlertId!);
Expand All @@ -70,6 +70,6 @@ public async ValueTask<CommandResult> Handle(GetUserAlertsQuery request, Cancell
return result;
});

return CommandResult.FromValue(paginatedListAlerts);
return paginatedListAlerts;
}
}
37 changes: 23 additions & 14 deletions src/Application/Alerts/Queries/SearchAlerts/SearchAlertQuery.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using Application.Alerts.Dtos;
using Dapper;
using Mediator;
using FluentValidation;
using SiteWatcher.Application.Common.Command;
using SiteWatcher.Application.Common.Queries;
using SiteWatcher.Application.Common.Results;
using SiteWatcher.Application.Interfaces;
using SiteWatcher.Common.Services;
using SiteWatcher.Domain.Alerts.DTOs;
Expand All @@ -11,33 +13,36 @@

namespace SiteWatcher.Application.Alerts.Commands.SearchAlerts;

public class SearchAlertQuery : IQuery<IEnumerable<SimpleAlertView>>, ICacheable
public class SearchAlertQuery : ICacheable
{
public string Term { get; set; } = null!;
public TimeSpan Expiration => TimeSpan.FromMinutes(10);
public string HashFieldName => $"Term:{Term}";

public string GetKey(ISession session) =>
CacheKeys.UserAlertSearch(session.UserId!.Value);
}

public class SearchAlertQueryHandler : IQueryHandler<SearchAlertQuery, IEnumerable<SimpleAlertView>>
public class SearchAlertQueryHandler : BaseHandler<SearchAlertQuery, Result<IEnumerable<SimpleAlertView>>>
{
private readonly IDapperContext _context;
private readonly IQueries _queries;
private readonly ISession _session;
private readonly IIdHasher _idHasher;

public SearchAlertQueryHandler(IDapperContext context, IQueries queries, ISession session, IIdHasher idHasher)
public SearchAlertQueryHandler(IDapperContext context, IQueries queries, ISession session, IIdHasher idHasher,
IValidator<SearchAlertQuery> validator) : base(validator)
{
_context = context;
_queries = queries;
_session = session;
_idHasher = idHasher;
}

public async ValueTask<IEnumerable<SimpleAlertView>> Handle(SearchAlertQuery request, CancellationToken cancellationToken)
protected override async Task<Result<IEnumerable<SimpleAlertView>>> HandleCommand(SearchAlertQuery command,
CancellationToken ct)
{
var searchTerms = request
var searchTerms = command
.Term.Split(' ')
.Where(t => !string.IsNullOrEmpty(t))
.Select(t => t.ToLowerCaseWithoutDiacritics()).ToArray();
Expand All @@ -46,13 +51,17 @@ public async ValueTask<IEnumerable<SimpleAlertView>> Handle(SearchAlertQuery req

var simpleAlertViewDtos = await _context
.UsingConnectionAsync(conn =>
{
var cmd = new CommandDefinition(
query.Sql,
query.Parameters,
cancellationToken: cancellationToken);
return conn.QueryAsync<SimpleAlertViewDto>(cmd);
});
return simpleAlertViewDtos.Select(dto => dto.ToSimpleAlertView(_idHasher));
{
var cmd = new CommandDefinition(
query.Sql,
query.Parameters,
cancellationToken: ct);
return conn.QueryAsync<SimpleAlertViewDto>(cmd);
});

var simpleAlertViews = simpleAlertViewDtos
.Select(dto => dto.ToSimpleAlertView(_idHasher));

return new Result<IEnumerable<SimpleAlertView>>(simpleAlertViews);
}
}
31 changes: 31 additions & 0 deletions src/Application/Common/BaseHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using FluentValidation;
using SiteWatcher.Application.Common.Results;
using SiteWatcher.Domain.Common.Errors;

namespace SiteWatcher.Application.Common.Command;

public abstract class BaseHandler<T,R> : IApplicationHandler where R : IResult, new()
{
private readonly IValidator<T> _validator;

protected BaseHandler(IValidator<T> validator)
{
_validator = validator;
}

public async Task<R> Handle(T command, CancellationToken ct)
{
var res = _validator.Validate(command);
if (res.IsValid)
return await HandleCommand(command, ct);

var errors = res.Errors.Select(err => err.ErrorMessage).ToArray();
var errorResult = new R();
errorResult.SetError(Error.Validation(errors));
return errorResult;
}

protected abstract Task<R> HandleCommand(T command, CancellationToken ct);
}

public interface IApplicationHandler{}
39 changes: 0 additions & 39 deletions src/Application/Common/Commands/CommandResult.cs

This file was deleted.

1 change: 0 additions & 1 deletion src/Application/Common/Constants/ApplicationErrors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ namespace SiteWatcher.Application.Common.Constants;

public static class ApplicationErrors
{
// TODO: Translate error messages at the fronteend
public static readonly string INTERNAL_ERROR = "An error has occurred.";
public static readonly string NAME_MUST_HAVE_ONLY_LETTERS = "Username must only have letters.";
public static readonly string USER_DO_NOT_EXIST = "User does not exist.";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
namespace SiteWatcher.Application.Common.Queries;

public sealed class QueryResult
public sealed class DbQuery
{
public QueryResult(string sql, Dictionary<string, object> parameters)
public DbQuery(string sql, Dictionary<string, object> parameters)
{
Sql = sql;
Parameters = parameters;
Expand Down
Loading

1 comment on commit 1145a27

@vercel
Copy link

@vercel vercel bot commented on 1145a27 Nov 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

site-watcher – ./

site-watcher-git-main-xilapa.vercel.app
site-watcher-xi.vercel.app
site-watcher-xilapa.vercel.app

Please sign in to comment.