Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
abdb841
Configuration Done
MashrafeJess Nov 16, 2025
848e960
update DB
MashrafeJess Nov 16, 2025
4a794d3
Final
MashrafeJess Nov 19, 2025
cbdd96f
Without Migration Folder
MashrafeJess Nov 19, 2025
55ba698
Initial commit on new branch
MashrafeJess Nov 19, 2025
2dccfbc
Merge branch 'recover-pr' into mashrafe
MashrafeJess Nov 19, 2025
7bdf898
recover
MashrafeJess Nov 19, 2025
c9a7de6
Update src/Application/EmailVerification/Create/CreateEmailVerificati…
MashrafeJess Nov 20, 2025
2e0968d
Update src/Application/EmailVerification/Delete/DeleteEmailVerificati…
MashrafeJess Nov 20, 2025
2783ecd
Update src/Application/PasswordResets/Get/GetPasswordResetQueryHandle…
MashrafeJess Nov 20, 2025
7a83e75
Update src/Application/EmailVerification/Update/UpdateEmailVerificati…
MashrafeJess Nov 20, 2025
e029c32
Update src/Application/PasswordResets/Create/CreatePasswordResetComma…
MashrafeJess Nov 20, 2025
92d3bfe
Update src/Application/EmailVerification/Create/CreateEmailVerificati…
MashrafeJess Nov 20, 2025
482565e
Update src/Application/Application/Create/CreateApplicationCommand.cs
MashrafeJess Nov 20, 2025
cc674bf
Resolve merge + restore local changes
MashrafeJess Nov 20, 2025
7f267f5
Update src/Application/PasswordResets/Get/GetPasswordResetQueryHandle…
MashrafeJess Nov 20, 2025
0885a52
Update src/Application/PasswordResets/Delete/DeletePasswordResetComma…
MashrafeJess Nov 20, 2025
c2918a4
Update src/Application/EmailVerification/Create/CreateEmailVerificati…
MashrafeJess Nov 20, 2025
133f8fc
2nd Resolve Done
MashrafeJess Nov 20, 2025
a409b55
Resolve merge + restore local changes
MashrafeJess Nov 20, 2025
5d28313
3rd
MashrafeJess Nov 20, 2025
1049735
Resolve merge + restore local changes
MashrafeJess Nov 20, 2025
83a7ad9
Update src/Application/EmailVerification/Create/CreateEmailVerificati…
MashrafeJess Nov 20, 2025
b588e97
4th Review
MashrafeJess Nov 20, 2025
6915bf5
Merge branch 'mashrafe' of https://github.com/Dapplesoft-AD/AuthServe…
MashrafeJess Nov 20, 2025
728d276
Resolve Conflict
MashrafeJess Nov 23, 2025
afccf5a
5th
MashrafeJess Nov 24, 2025
575b2a1
6
MashrafeJess Nov 24, 2025
ab06a0a
Merge branch 'Dev' of https://github.com/Dapplesoft-AD/AuthServer int…
MashrafeJess Nov 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -403,3 +403,4 @@ FodyWeavers.xsd
appsettings.Development.json
appsettings.*.json
!appsettings.json
/AuthServer.sln
4 changes: 2 additions & 2 deletions AuthServer.sln
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
# Visual Studio Version 18
VisualStudioVersion = 18.3.11206.111 d18.3
Comment on lines +2 to +3
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

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

Invalid Visual Studio version. The VisualStudioVersion "18.3.11206.111 d18.3" appears to be corrupted or invalid. Visual Studio 2022 uses version 17.x, not 18.x. This should be reverted to a valid version number.

Suggested change
# Visual Studio Version 18
VisualStudioVersion = 18.3.11206.111 d18.3
# Visual Studio Version 17
VisualStudioVersion = 17.3.32619.126

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This File looks Critical and changing the version for this project may harm our main progress.

MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{827E0CD3-B72D-47B6-A68D-7590B98EB39B}"
EndProject
Expand Down
2 changes: 1 addition & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<PackageVersion Include="Scrutor" Version="6.1.0" />
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="12.0.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="9.0.11" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.9" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.11" />
<PackageVersion Include="Serilog" Version="4.3.0" />
<!-- Infrastructure -->
<PackageVersion Include="AspNetCore.HealthChecks.NpgSql" Version="9.0.0" />
Expand Down
Empty file added dotnet
Empty file.
Empty file.
12 changes: 12 additions & 0 deletions src/Application/Abstractions/Data/IApplicationDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
using Domain.Applications;
using Domain.Customers;
using Domain.EmailVerification;
using Domain.PasswordResets;
using Domain.Permissions;
using Domain.RolePermissions;
using Domain.Roles;
using Domain.Todos;
using Domain.Token;
using Domain.UserLoginHistories;
using Domain.UserProfiles;
using Domain.Users;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;

namespace Application.Abstractions.Data;

public interface IApplicationDbContext
{
DbSet<User> Users { get; }
DbSet<EmailVerifications> EmailVerifications { get; }
DbSet<PasswordReset> PasswordReset { get; }
DbSet<Tokens> Tokens { get; }
DbSet<TodoItem> TodoItems { get; }
DbSet<Customer> Customers { get; }
DbSet<Permission> Permissions { get; }
DbSet<Applicationapply> Applications { get; } // ← ADD THIS
DbSet<RolePermission> RolePermissions { get; }
DbSet<Role> Roles { get; }
DbSet<UserLoginHistory> UserLoginHistory { get; }
DbSet<UserProfile> UserProfile { get; }
EntityEntry Entry(object entity);
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
2 changes: 1 addition & 1 deletion src/Application/Customers/Create/CreateCustomerCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Application.Customers.Create;

public sealed class CreateCustomerCommand: ICommand<Guid>
public sealed class CreateCustomerCommand : ICommand<Guid>
{
public string Name { get; set; }
public string Email { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Application.Customers.Create;

public class CreateCustomerValidator: AbstractValidator<CreateCustomerCommand>
public class CreateCustomerValidator : AbstractValidator<CreateCustomerCommand>
{
public CreateCustomerValidator()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Application.Abstractions.Messaging;

namespace Application.EmailVerification.Create;

public sealed class CreateEmailVerificationCommand : ICommand<Guid>
{
public Guid UserId { get; set; }
public string Token { get; set; }
public DateTime ExpiresAt { get; set; }
public DateTime VerifiedAt { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using Application.Abstractions.Authentication;
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.EmailVerification;
using Domain.Users;
using Microsoft.EntityFrameworkCore;
using SharedKernel;

namespace Application.EmailVerification.Create;

internal sealed class CreateEmailVerificationCommandHandler(
IApplicationDbContext context,
IDateTimeProvider dateTimeProvider,
IUserContext userContext)
: ICommandHandler<CreateEmailVerificationCommand, Guid>
{
public async Task<Result<Guid>> Handle(CreateEmailVerificationCommand command, CancellationToken cancellationToken)
{
if (userContext.UserId != command.UserId)
{
return Result.Failure<Guid>(UserErrors.Unauthorized());
}

User? user = await context.Users.AsNoTracking()
.SingleOrDefaultAsync(u => u.Id == command.UserId, cancellationToken);

if (user is null)
{
return Result.Failure<Guid>(UserErrors.NotFound(command.UserId));
}

var emailVerifications = new EmailVerifications
{
UserId = command.UserId,
Token = command.Token,
ExpiresAt = command.ExpiresAt == default
? dateTimeProvider.UtcNow
: command.ExpiresAt,
VerifiedAt = command.VerifiedAt == default
? dateTimeProvider.UtcNow
: command.VerifiedAt
};

emailVerifications.Raise(new EmailVerificationCreatedDomainEvent(emailVerifications.EvId));

context.EmailVerifications.Add(emailVerifications);

await context.SaveChangesAsync(cancellationToken);

return emailVerifications.EvId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using FluentValidation;

namespace Application.EmailVerification.Create;

public class CreateEmailVerificationCommandValidator : AbstractValidator<CreateEmailVerificationCommand>
{
public CreateEmailVerificationCommandValidator()
{
RuleFor(x => x.UserId)
.NotEmpty().WithMessage("User ID is required.");
RuleFor(x => x.Token)
.NotEmpty().WithMessage("Token is required.")
.MaximumLength(255).WithMessage("Token must not exceed 255 characters.");
RuleFor(x => x.ExpiresAt)
.GreaterThan(DateTime.UtcNow).WithMessage("Expiration date must be in the future.");
RuleFor(x => x.VerifiedAt)
.GreaterThan(DateTime.UtcNow).WithMessage("Verification date must be in the future.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Application.Abstractions.Messaging;

namespace Application.EmailVerification.Delete;

public sealed record DeleteEmailVerificationCommand(Guid EvId) : ICommand;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using Application.Abstractions.Authentication;
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.EmailVerification;
using Microsoft.EntityFrameworkCore;
using SharedKernel;

namespace Application.EmailVerification.Delete;

internal sealed class DeleteEmailVerificationCommandHandler(IApplicationDbContext context, IUserContext userContext)
: ICommandHandler<DeleteEmailVerificationCommand>
{
public async Task<Result> Handle(DeleteEmailVerificationCommand command, CancellationToken cancellationToken)
{
EmailVerifications? emailVerifications = await context.EmailVerifications
.SingleOrDefaultAsync(t => t.EvId == command.EvId && t.UserId == userContext.UserId, cancellationToken);

if (emailVerifications is null)
{
return Result.Failure(EmailVerificationErrors.NotFound(command.EvId));
}

context.EmailVerifications.Remove(emailVerifications);

emailVerifications.Raise(new EmailVerificationDeletedDomainEvent(emailVerifications.EvId));

await context.SaveChangesAsync(cancellationToken);

return Result.Success();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using FluentValidation;

namespace Application.EmailVerification.Delete;

internal sealed class DeleteEmailVerificationCommandValidator : AbstractValidator<DeleteEmailVerificationCommand>
{
public DeleteEmailVerificationCommandValidator()
{
RuleFor(x => x.EvId)
.NotEmpty().WithMessage("Email Verification ID is required.");
}
}
10 changes: 10 additions & 0 deletions src/Application/EmailVerification/Get/EmailVerificationResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Application.EmailVerification.Get;

public sealed class EmailVerificationResponse
{
public Guid EvId { get; set; }
public Guid UserId { get; set; }
public string Token { get; set; }
public DateTime ExpiresAt { get; set; }
public DateTime VerifiedAt { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Application.Abstractions.Messaging;

namespace Application.EmailVerification.Get;

public sealed record GetEmailVerificationsQuery(Guid UserId) : IQuery<List<EmailVerificationResponse>>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using Application.Abstractions.Authentication;
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.Users;
using Microsoft.EntityFrameworkCore;
using SharedKernel;

namespace Application.EmailVerification.Get;

internal sealed class GetEmailVerificationQueryHandler(IApplicationDbContext context, IUserContext userContext)
: IQueryHandler<GetEmailVerificationsQuery, List<EmailVerificationResponse>>
{
public async Task<Result<List<EmailVerificationResponse>>> Handle(GetEmailVerificationsQuery query, CancellationToken cancellationToken)
{
if (query.UserId != userContext.UserId)
{
return Result.Failure<List<EmailVerificationResponse>>(UserErrors.Unauthorized());
}

List<EmailVerificationResponse> emailVerifications = await context.EmailVerifications
.Where(emailVerifications => emailVerifications.UserId == query.UserId)
.Select(emailVerifications => new EmailVerificationResponse
{
EvId = emailVerifications.EvId,
UserId = emailVerifications.UserId,
Token = emailVerifications.Token,
ExpiresAt = emailVerifications.ExpiresAt,
VerifiedAt = emailVerifications.VerifiedAt
}).ToListAsync(cancellationToken);

return emailVerifications;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Application.EmailVerification.GetById;

public sealed class EmailVerificationResponse
{
public Guid EvId { get; set; }
public Guid UserId { get; set; }
public string Token { get; set; }
public DateTime ExpiresAt { get; set; }
public DateTime VerifiedAt { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using Application.Abstractions.Messaging;

namespace Application.EmailVerification.GetById;

public sealed record GetEmailVerificationByIdQuery(Guid EvId) : IQuery<EmailVerificationResponse>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Application.Abstractions.Authentication;
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.EmailVerification;
using Microsoft.EntityFrameworkCore;
using SharedKernel;

namespace Application.EmailVerification.GetById;

internal sealed class GetEmailVerificationByIdQueryHandler(IApplicationDbContext context, IUserContext userContext)
: IQueryHandler<GetEmailVerificationByIdQuery, EmailVerificationResponse>
{
public async Task<Result<EmailVerificationResponse>> Handle(GetEmailVerificationByIdQuery query, CancellationToken cancellationToken)
{
EmailVerificationResponse? emailVerification = await context.EmailVerifications
.Where(emailVerification => emailVerification.EvId == query.EvId && emailVerification.UserId == userContext.UserId)
.Select(emailVerification => new EmailVerificationResponse
{
EvId = emailVerification.EvId,
UserId = emailVerification.UserId,
Token = emailVerification.Token,
ExpiresAt = emailVerification.ExpiresAt,
VerifiedAt = emailVerification.VerifiedAt
})
.SingleOrDefaultAsync(cancellationToken);

if (emailVerification is null)
{
return Result.Failure<EmailVerificationResponse>(EmailVerificationErrors.NotFound(query.EvId));
}

return emailVerification;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Application.Abstractions.Messaging;

namespace Application.EmailVerification.Update;

public sealed record UpdateEmailVerificationCommand(
Guid EvId,
string Token) : ICommand;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Application.Abstractions.Data;
using Application.Abstractions.Messaging;
using Domain.EmailVerification;
using Microsoft.EntityFrameworkCore;
using SharedKernel;

namespace Application.EmailVerification.Update;

internal sealed class UpdateEmailVerificationCommandHandler(
IApplicationDbContext context)
: ICommandHandler<UpdateEmailVerificationCommand>
{
public async Task<Result> Handle(UpdateEmailVerificationCommand command, CancellationToken cancellationToken)
{
EmailVerifications? emailVerifications = await context.EmailVerifications
.SingleOrDefaultAsync(t => t.EvId == command.EvId, cancellationToken);

if (emailVerifications is null)
{
return Result.Failure(EmailVerificationErrors.NotFound(command.EvId));
}

emailVerifications.Token = command.Token;

await context.SaveChangesAsync(cancellationToken);

return Result.Success();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Application.Abstractions.Messaging;

namespace Application.PasswordResets.Create;

public sealed class CreatePasswordResetCommand : ICommand<Guid>
{
public Guid UserId { get; set; }
public string Token { get; set; }
public DateTime ExpiresAt { get; set; }
public bool Used { get; set; }
}
Loading