feat: upgraded to .NET 10 + add API app
This commit is contained in:
13
.idea/.idea.Bahla.Backend/.idea/.gitignore
generated
vendored
Normal file
13
.idea/.idea.Bahla.Backend/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/modules.xml
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/.idea.Bahla.Backend.iml
|
||||||
|
/contentModel.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
1
.idea/.idea.Bahla.Backend/.idea/.name
generated
Normal file
1
.idea/.idea.Bahla.Backend/.idea/.name
generated
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Bahla.Backend
|
||||||
4
.idea/.idea.Bahla.Backend/.idea/encodings.xml
generated
Normal file
4
.idea/.idea.Bahla.Backend/.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
||||||
8
.idea/.idea.Bahla.Backend/.idea/indexLayout.xml
generated
Normal file
8
.idea/.idea.Bahla.Backend/.idea/indexLayout.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
12
.idea/.idea.Bahla.Backend/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
12
.idea/.idea.Bahla.Backend/.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<component name="InspectionProjectProfileManager">
|
||||||
|
<profile version="1.0">
|
||||||
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="GrazieInspection" enabled="false" level="GRAMMAR_ERROR" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="LanguageDetectionInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||||
|
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||||
|
<option name="processCode" value="true" />
|
||||||
|
<option name="processLiterals" value="true" />
|
||||||
|
<option name="processComments" value="true" />
|
||||||
|
</inspection_tool>
|
||||||
|
</profile>
|
||||||
|
</component>
|
||||||
6
.idea/.idea.Bahla.Backend/.idea/vcs.xml
generated
Normal file
6
.idea/.idea.Bahla.Backend/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
5
Bahla.Backend.slnx
Normal file
5
Bahla.Backend.slnx
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<Solution>
|
||||||
|
<Project Path="src/Bahla.Domain/Bahla.Domain.csproj" />
|
||||||
|
<Project Path="src/Bahla.Persistence/Bahla.Persistence.csproj" />
|
||||||
|
<Project Path="src/Bahla.Tests/Bahla.Tests.csproj" />
|
||||||
|
</Solution>
|
||||||
10
src/Bahla.API/Bahla.API.csproj
Normal file
10
src/Bahla.API/Bahla.API.csproj
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
9
src/Bahla.API/Program.cs
Normal file
9
src/Bahla.API/Program.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
builder.Services.AddProblemDetails();
|
||||||
|
builder.Services.AddOpenApi();
|
||||||
|
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
|
||||||
|
app.MapGet("/helloWorld", () => "Hello, World!");
|
||||||
12
src/Bahla.API/Properties/launchSettings.json
Normal file
12
src/Bahla.API/Properties/launchSettings.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Bahla.API": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"applicationUrl": "https://localhost:63146;http://localhost:63147"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
using Bahla.Domain.Entities.Base;
|
using Bahla.Domain.Entities.Base;
|
||||||
|
|
||||||
namespace Bahla.Domain.Builders.Base
|
namespace Bahla.Domain.Builders.Base;
|
||||||
|
|
||||||
|
public interface IEntityBuilder<out T> where T : IEntity
|
||||||
{
|
{
|
||||||
public interface IEntityBuilder<out T> where T : IEntity
|
/// <summary>
|
||||||
{
|
/// Build the entity.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Build the entity.
|
/// <returns>Entity</returns>
|
||||||
/// </summary>
|
T Build();
|
||||||
/// <returns>Entity</returns>
|
|
||||||
T Build();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,36 @@
|
|||||||
using Bahla.Domain.Entities;
|
using Bahla.Domain.Entities;
|
||||||
using Bahla.Domain.Types;
|
using Bahla.Domain.Types;
|
||||||
|
|
||||||
namespace Bahla.Domain.Builders.Base
|
namespace Bahla.Domain.Builders.Base;
|
||||||
|
|
||||||
|
public interface IRoleBuilder : IEntityBuilder<Role>
|
||||||
{
|
{
|
||||||
public interface IRoleBuilder : IEntityBuilder<Role>
|
/// <summary>
|
||||||
{
|
/// Defines the identifier for the role, if not provided, a new identifier will be generated.
|
||||||
/// <summary>
|
/// </summary>
|
||||||
/// Defines the identifier for the role, if not provided, a new identifier will be generated.
|
/// <param name="identifier">Identifier</param>
|
||||||
/// </summary>
|
/// <returns>Builder</returns>
|
||||||
/// <param name="identifier">Identifier</param>
|
IRoleBuilder WithIdentifier(Identifier identifier);
|
||||||
/// <returns>Builder</returns>
|
|
||||||
IRoleBuilder WithIdentifier(Identifier identifier);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the name for the role.
|
/// Defines the name for the role.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="roleName">Role name</param>
|
/// <param name="roleName">Role name</param>
|
||||||
/// <returns>Builder</returns>
|
/// <returns>Builder</returns>
|
||||||
IRoleBuilder WithName(string roleName);
|
IRoleBuilder WithName(string roleName);
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the value mask for the role. Maximum allowed is 32 bits (1 << 32).
|
/// Defines the value mask for the role. Maximum allowed is 32 bits (1 << 32).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="valueMask">Role bitmask</param>
|
/// <param name="valueMask">Role bitmask</param>
|
||||||
/// <returns>Builder</returns>
|
/// <returns>Builder</returns>
|
||||||
IRoleBuilder WithValueMask(uint valueMask);
|
IRoleBuilder WithValueMask(uint valueMask);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clones the role.
|
/// Clones the role.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="role">Role</param>
|
/// <param name="role">Role</param>
|
||||||
/// <returns>Builder</returns>
|
/// <returns>Builder</returns>
|
||||||
IRoleBuilder Clone(Role role);
|
IRoleBuilder Clone(Role role);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/Bahla.Domain/Builders/Base/IUserBuilder.cs
Normal file
25
src/Bahla.Domain/Builders/Base/IUserBuilder.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
using Bahla.Domain.Entities;
|
||||||
|
using Bahla.Domain.Enums;
|
||||||
|
|
||||||
|
namespace Bahla.Domain.Builders.Base;
|
||||||
|
|
||||||
|
public interface IUserBuilder : IEntityBuilder<User>
|
||||||
|
{
|
||||||
|
IUserBuilder WithEmail(string email);
|
||||||
|
|
||||||
|
IUserBuilder WithFirstname(string firstname);
|
||||||
|
|
||||||
|
IUserBuilder WithLastname(string lastname);
|
||||||
|
|
||||||
|
IUserBuilder WithRole(Role role);
|
||||||
|
|
||||||
|
IUserBuilder WithGender(Gender gender);
|
||||||
|
|
||||||
|
IUserBuilder WithBirthday(DateTime birthday);
|
||||||
|
|
||||||
|
IUserBuilder WithJoinedOn(DateTime joinedOn);
|
||||||
|
|
||||||
|
IUserBuilder WithSalt(IReadOnlyCollection<byte> salt);
|
||||||
|
|
||||||
|
IUserBuilder WithVerifier(IReadOnlyCollection<byte> verifier);
|
||||||
|
}
|
||||||
70
src/Bahla.Domain/Builders/UserBuilder.cs
Normal file
70
src/Bahla.Domain/Builders/UserBuilder.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using Bahla.Domain.Builders.Base;
|
||||||
|
using Bahla.Domain.Entities;
|
||||||
|
using Bahla.Domain.Enums;
|
||||||
|
using Bahla.Domain.Types;
|
||||||
|
|
||||||
|
namespace Bahla.Domain.Builders;
|
||||||
|
|
||||||
|
public sealed class UserBuilder : IUserBuilder
|
||||||
|
{
|
||||||
|
internal Identifier _identifier;
|
||||||
|
internal string _email;
|
||||||
|
internal string _firstname;
|
||||||
|
internal string _lastname;
|
||||||
|
internal Role _role;
|
||||||
|
internal Gender _gender;
|
||||||
|
internal DateTime _birthday;
|
||||||
|
internal DateTime _joinedDate;
|
||||||
|
internal IReadOnlyCollection<byte> _salt;
|
||||||
|
internal IReadOnlyCollection<byte> _verifier;
|
||||||
|
|
||||||
|
public User Build()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUserBuilder WithEmail(string email)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUserBuilder WithFirstname(string firstname)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUserBuilder WithLastname(string lastname)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUserBuilder WithRole(Role role)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUserBuilder WithGender(Gender gender)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUserBuilder WithBirthday(DateTime birthday)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUserBuilder WithJoinedOn(DateTime joinedOn)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUserBuilder WithSalt(IReadOnlyCollection<byte> salt)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IUserBuilder WithVerifier(IReadOnlyCollection<byte> verifier)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ namespace Bahla.Domain.Entities
|
|||||||
{
|
{
|
||||||
public string RoleName { get; init; }
|
public string RoleName { get; init; }
|
||||||
public uint ValueMask { get; init; }
|
public uint ValueMask { get; init; }
|
||||||
internal Role(Identifier identifier, string roleName, uint valueMask) : base(identifier)
|
private Role(Identifier identifier, string roleName, uint valueMask) : base(identifier)
|
||||||
{
|
{
|
||||||
RoleName = roleName;
|
RoleName = roleName;
|
||||||
ValueMask = valueMask;
|
ValueMask = valueMask;
|
||||||
|
|||||||
52
src/Bahla.Domain/Entities/User.cs
Normal file
52
src/Bahla.Domain/Entities/User.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
using Bahla.Domain.Builders;
|
||||||
|
using Bahla.Domain.Builders.Base;
|
||||||
|
using Bahla.Domain.Enums;
|
||||||
|
using Bahla.Domain.Types;
|
||||||
|
using Bahla.Domain.Entities.Base;
|
||||||
|
|
||||||
|
namespace Bahla.Domain.Entities;
|
||||||
|
|
||||||
|
public sealed record User : Entity
|
||||||
|
{
|
||||||
|
public string Email { get; init; }
|
||||||
|
public string Firstname { get; init; }
|
||||||
|
public string Lastname { get; init; }
|
||||||
|
public Role Role { get; init; }
|
||||||
|
public Gender Gender { get; init; }
|
||||||
|
public DateTime Birthday { get; init; }
|
||||||
|
public DateTime JoinedAt { get; init; }
|
||||||
|
public IReadOnlyCollection<byte> Salt { get; init; }
|
||||||
|
public IReadOnlyCollection<byte> Verifier { get; init; }
|
||||||
|
|
||||||
|
private User(Identifier identifier, string email, string firstname, string lastname, Role role, Gender gender, DateTime birthday, DateTime joinedAt, IReadOnlyCollection<byte> salt, IReadOnlyCollection<byte> verifier) : base(identifier)
|
||||||
|
{
|
||||||
|
Email = email;
|
||||||
|
Firstname = firstname;
|
||||||
|
Lastname = lastname;
|
||||||
|
Role = role;
|
||||||
|
Gender = gender;
|
||||||
|
Birthday = birthday;
|
||||||
|
JoinedAt = joinedAt;
|
||||||
|
Salt = salt;
|
||||||
|
Verifier = verifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal User(UserBuilder builder) : base(builder._identifier)
|
||||||
|
{
|
||||||
|
Email = builder._email;
|
||||||
|
Firstname = builder._firstname;
|
||||||
|
Lastname = builder._lastname;
|
||||||
|
Role = builder._role;
|
||||||
|
Gender = builder._gender;
|
||||||
|
Birthday = builder._birthday;
|
||||||
|
JoinedAt = builder._joinedDate;
|
||||||
|
Salt = builder._salt;
|
||||||
|
Verifier = builder._verifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the builder
|
||||||
|
/// </summary>
|
||||||
|
public static IUserBuilder Builder => new UserBuilder();
|
||||||
|
|
||||||
|
}
|
||||||
2
src/Bahla.Domain/Enums/Gender.cs
Normal file
2
src/Bahla.Domain/Enums/Gender.cs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
namespace Bahla.Domain.Enums;
|
||||||
|
public enum Gender { Male, Female, }
|
||||||
@@ -3,10 +3,10 @@ using Bahla.Domain.Specifications.Base;
|
|||||||
|
|
||||||
namespace Bahla.Domain.Specifications
|
namespace Bahla.Domain.Specifications
|
||||||
{
|
{
|
||||||
public sealed class AndNotSpecification<T>(IEntitySpecification<T> left, IEntitySpecification<T> right) : CompositeSpecification<T> where T : IEntity
|
public sealed class AndNotSpecification<T>(ISpecification<T> left, ISpecification<T> right) : CompositeSpecification<T> where T : class
|
||||||
{
|
{
|
||||||
private readonly IEntitySpecification<T> _left = left;
|
private readonly ISpecification<T> _left = left;
|
||||||
private readonly IEntitySpecification<T> _right = right;
|
private readonly ISpecification<T> _right = right;
|
||||||
|
|
||||||
public override bool IsSatisfiedBy(T entity)
|
public override bool IsSatisfiedBy(T entity)
|
||||||
=> _left.IsSatisfiedBy(entity) && !_right.IsSatisfiedBy(entity);
|
=> _left.IsSatisfiedBy(entity) && !_right.IsSatisfiedBy(entity);
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
using Bahla.Domain.Entities.Base;
|
using Bahla.Domain.Specifications.Base;
|
||||||
using Bahla.Domain.Specifications.Base;
|
|
||||||
|
|
||||||
namespace Bahla.Domain.Specifications
|
namespace Bahla.Domain.Specifications;
|
||||||
|
|
||||||
|
public sealed class AndSpecification<T>(ISpecification<T> left, ISpecification<T> right) : CompositeSpecification<T> where T : class
|
||||||
{
|
{
|
||||||
public sealed class AndSpecification<T>(IEntitySpecification<T> left, IEntitySpecification<T> right) : CompositeSpecification<T> where T : IEntity
|
private readonly ISpecification<T> _left = left;
|
||||||
{
|
private readonly ISpecification<T> _right = right;
|
||||||
private readonly IEntitySpecification<T> _left = left;
|
public override bool IsSatisfiedBy(T entity)
|
||||||
private readonly IEntitySpecification<T> _right = right;
|
=> _left.IsSatisfiedBy(entity) && _right.IsSatisfiedBy(entity);
|
||||||
public override bool IsSatisfiedBy(T entity)
|
|
||||||
=> _left.IsSatisfiedBy(entity) && _right.IsSatisfiedBy(entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,24 +1,17 @@
|
|||||||
using Bahla.Domain.Entities.Base;
|
namespace Bahla.Domain.Specifications.Base
|
||||||
using Bahla.Domain.Specifications.Base;
|
|
||||||
|
|
||||||
namespace Bahla.Domain.Specifications
|
|
||||||
{
|
{
|
||||||
public abstract class CompositeSpecification<T> : IEntitySpecification<T> where T : IEntity
|
public abstract class CompositeSpecification<T> : ISpecification<T> where T : class
|
||||||
{
|
{
|
||||||
public abstract bool IsSatisfiedBy(T entity);
|
public abstract bool IsSatisfiedBy(T entity);
|
||||||
|
public ISpecification<T> And(ISpecification<T> specification)
|
||||||
public IEntitySpecification<T> And(IEntitySpecification<T> specification)
|
=> new AndSpecification<T>(this, specification);
|
||||||
=> new AndSpecification(this, specification);
|
public ISpecification<T> AndNot(ISpecification<T> specification)
|
||||||
|
=> new AndNotSpecification<T>(this, specification);
|
||||||
public IEntitySpecification<T> AndNot(IEntitySpecification<T> specification)
|
public ISpecification<T> Not()
|
||||||
=> new AndNotSpecification(this, specification);
|
=> new NotSpecification<T>(this);
|
||||||
public IEntitySpecification<T> Not()
|
public ISpecification<T> Or(ISpecification<T> specification)
|
||||||
=> new NotSpecification(this);
|
=> new OrSpecification<T>(this, specification);
|
||||||
|
public ISpecification<T> OrNot(ISpecification<T> specification)
|
||||||
public IEntitySpecification<T> Or(IEntitySpecification<T> specification)
|
=> new OrNotSpecification<T>(this, specification);
|
||||||
=> new OrSpecification(this, specification);
|
|
||||||
|
|
||||||
IEntitySpecification<T> OrNot(IEntitySpecification<T> specification)
|
|
||||||
=> new OrNotSpecification(this, specification);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
using Bahla.Domain.Entities.Base;
|
|
||||||
|
|
||||||
namespace Bahla.Domain.Specifications.Base
|
|
||||||
{
|
|
||||||
public interface IEntitySpecification<T> where T : IEntity
|
|
||||||
{
|
|
||||||
bool IsSatisfiedBy(T entity);
|
|
||||||
IEntitySpecification<T> And(IEntitySpecification<T> other);
|
|
||||||
IEntitySpecification<T> AndNot(IEntitySpecification<T> other);
|
|
||||||
IEntitySpecification<T> Or(IEntitySpecification<T> other);
|
|
||||||
IEntitySpecification<T> OrNot(IEntitySpecification<T> other);
|
|
||||||
IEntitySpecification<T> Not();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
15
src/Bahla.Domain/Specifications/Base/ISpecification.cs
Normal file
15
src/Bahla.Domain/Specifications/Base/ISpecification.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Bahla.Domain.Entities.Base;
|
||||||
|
|
||||||
|
namespace Bahla.Domain.Specifications.Base
|
||||||
|
{
|
||||||
|
public interface ISpecification<T> where T : class
|
||||||
|
{
|
||||||
|
bool IsSatisfiedBy(T entity);
|
||||||
|
ISpecification<T> And(ISpecification<T> other);
|
||||||
|
ISpecification<T> AndNot(ISpecification<T> other);
|
||||||
|
ISpecification<T> Or(ISpecification<T> other);
|
||||||
|
ISpecification<T> OrNot(ISpecification<T> other);
|
||||||
|
ISpecification<T> Not();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
using Bahla.Domain.Entities.Base;
|
using Bahla.Domain.Entities.Base;
|
||||||
using Bahla.Domain.Specifications.Base;
|
using Bahla.Domain.Specifications.Base;
|
||||||
|
|
||||||
namespace Bahla.Domain.Specifications
|
namespace Bahla.Domain.Specifications;
|
||||||
|
|
||||||
|
public sealed class NotSpecification<T>(ISpecification<T> other) : CompositeSpecification<T> where T : class
|
||||||
{
|
{
|
||||||
public sealed class NotSpecification<T>(IEntitySpecification<T> other) : CompositeSpecification<T> where T : IEntity
|
private readonly ISpecification<T> _other = other;
|
||||||
{
|
public override bool IsSatisfiedBy(T entity)
|
||||||
private readonly IEntitySpecification<T> _other = other;
|
=> !_other.IsSatisfiedBy(entity);
|
||||||
public override bool IsSatisfiedBy(T entity)
|
|
||||||
=> !_other.IsSatisfiedBy(entity);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
using Bahla.Domain.Entities.Base;
|
using Bahla.Domain.Entities.Base;
|
||||||
using Bahla.Domain.Specifications.Base;
|
using Bahla.Domain.Specifications.Base;
|
||||||
|
|
||||||
namespace Bahla.Domain.Specifications
|
namespace Bahla.Domain.Specifications;
|
||||||
{
|
|
||||||
public sealed class OrNotSpecification<T>(IEntitySpecification<T> left, IEntitySpecification<T> right) : CompositeSpecification<T> where T : IEntity
|
|
||||||
{
|
|
||||||
private readonly IEntitySpecification<T> _left = left;
|
|
||||||
private readonly IEntitySpecification<T> _right = right;
|
|
||||||
|
|
||||||
public override bool IsSatisfiedBy(T entity)
|
public sealed class OrNotSpecification<T>(ISpecification<T> left, ISpecification<T> right) : CompositeSpecification<T> where T : class
|
||||||
=> _left.IsSatisfiedBy(entity) || !_right.IsSatisfiedBy(entity);
|
{
|
||||||
}
|
private readonly ISpecification<T> _left = left;
|
||||||
|
private readonly ISpecification<T> _right = right;
|
||||||
|
|
||||||
|
public override bool IsSatisfiedBy(T entity)
|
||||||
|
=> _left.IsSatisfiedBy(entity) || !_right.IsSatisfiedBy(entity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
using Bahla.Domain.Entities.Base;
|
using Bahla.Domain.Entities.Base;
|
||||||
using Bahla.Domain.Specifications.Base;
|
using Bahla.Domain.Specifications.Base;
|
||||||
|
|
||||||
namespace Bahla.Domain.Specifications
|
namespace Bahla.Domain.Specifications;
|
||||||
{
|
|
||||||
public sealed class OrSpecification<T>(IEntitySpecification<T> left, IEntitySpecification<T> right) : CompositeSpecification<T> where T : IEntity
|
|
||||||
{
|
|
||||||
private readonly IEntitySpecification<T> _left = left;
|
|
||||||
private readonly IEntitySpecification<T> _right = right;
|
|
||||||
|
|
||||||
public override bool IsSatisfiedBy(T entity)
|
public sealed class OrSpecification<T>(ISpecification<T> left, ISpecification<T> right) : CompositeSpecification<T> where T : class
|
||||||
=> _left.IsSatisfiedBy(entity) || _right.IsSatisfiedBy(entity);
|
{
|
||||||
}
|
private readonly ISpecification<T> _left = left;
|
||||||
|
private readonly ISpecification<T> _right = right;
|
||||||
|
|
||||||
|
public override bool IsSatisfiedBy(T entity)
|
||||||
|
=> _left.IsSatisfiedBy(entity) || _right.IsSatisfiedBy(entity);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace Bahla.Persistence
|
|
||||||
{
|
|
||||||
public class Class1
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net10.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
using Bahla.Domain.Entities;
|
|
||||||
using Bahla.Domain.Exceptions;
|
|
||||||
|
|
||||||
namespace Bahla.Tests.Builders
|
|
||||||
{
|
|
||||||
internal class BuilderTests
|
|
||||||
{
|
|
||||||
|
|
||||||
[Test, Description("Test to create a role through builder.")]
|
|
||||||
public void TestRoleBuilder()
|
|
||||||
{
|
|
||||||
var role = Role.Builder
|
|
||||||
.WithName("Administrator")
|
|
||||||
.WithValueMask(1 << 0)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
var clonedRole = Role.Builder
|
|
||||||
.Clone(role)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
Assert.Multiple(() =>
|
|
||||||
{
|
|
||||||
Assert.That(role.RoleName, Is.EqualTo(clonedRole.RoleName));
|
|
||||||
Assert.That(role.ValueMask, Is.EqualTo(clonedRole.ValueMask));
|
|
||||||
Assert.That(role.UUID, Is.EqualTo(clonedRole.UUID));
|
|
||||||
|
|
||||||
Assert.That(clonedRole, Is.Not.SameAs(role));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test, Description("Test to create a role with a empty or null name.")]
|
|
||||||
public void TestRoleBuilderBadName()
|
|
||||||
{
|
|
||||||
Assert.Throws<EntityBuilderException>(() =>
|
|
||||||
{
|
|
||||||
Role.Builder
|
|
||||||
.WithName("")
|
|
||||||
.WithValueMask(1 << 0)
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
72
src/Bahla.Tests/Builders/RoleBuilderTest.cs
Normal file
72
src/Bahla.Tests/Builders/RoleBuilderTest.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
using Bahla.Domain.Entities;
|
||||||
|
using Bahla.Domain.Exceptions;
|
||||||
|
|
||||||
|
namespace Bahla.Tests.Builders
|
||||||
|
{
|
||||||
|
internal class RoleBuilderTest
|
||||||
|
{
|
||||||
|
private const string R1Name = "Organisateur";
|
||||||
|
private const int R1ValueMask = 1 << 0;
|
||||||
|
|
||||||
|
private const string R2Name = "Animateur";
|
||||||
|
private const int R2ValueMask = 1 << 1;
|
||||||
|
|
||||||
|
private const string R3Name = "Bahla Bot";
|
||||||
|
private const int R3ValueMask = 1 << 2;
|
||||||
|
|
||||||
|
private const string R4Name = "Utilisateur";
|
||||||
|
private const int R4ValueMask = 1 << 3;
|
||||||
|
|
||||||
|
|
||||||
|
[Test, Description("Create 4 roles through builder and check if they're well created")]
|
||||||
|
public void TestRoleBuilder()
|
||||||
|
{
|
||||||
|
var r1 = Role.Builder
|
||||||
|
.WithName(R1Name)
|
||||||
|
.WithValueMask(R1ValueMask)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var r2 = Role.Builder
|
||||||
|
.WithName(R2Name)
|
||||||
|
.WithValueMask(R2ValueMask)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var r3 = Role.Builder
|
||||||
|
.WithName(R3Name)
|
||||||
|
.WithValueMask(R3ValueMask)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var r4 = Role.Builder
|
||||||
|
.WithName(R4Name)
|
||||||
|
.WithValueMask(R4ValueMask)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
|
Assert.That(r1.RoleName, Is.EqualTo(R1Name));
|
||||||
|
Assert.That(r1.ValueMask, Is.EqualTo(R1ValueMask));
|
||||||
|
|
||||||
|
Assert.That(r2.RoleName, Is.EqualTo(R2Name));
|
||||||
|
Assert.That(r2.ValueMask, Is.EqualTo(R2ValueMask));
|
||||||
|
|
||||||
|
Assert.That(r3.RoleName, Is.EqualTo(R3Name));
|
||||||
|
Assert.That(r3.ValueMask, Is.EqualTo(R3ValueMask));
|
||||||
|
|
||||||
|
Assert.That(r4.RoleName, Is.EqualTo(R4Name));
|
||||||
|
Assert.That(r4.ValueMask, Is.EqualTo(R4ValueMask));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test, Description("Create a role with an empty name and check if the builder throws a specification exception")]
|
||||||
|
public void TestRoleBuilderSpecification()
|
||||||
|
{
|
||||||
|
Assert.Throws<EntityBuilderException>(() =>
|
||||||
|
{
|
||||||
|
var r1 = Role.Builder
|
||||||
|
.Build();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
94
src/Bahla.Tests/TestDataProvider.cs
Normal file
94
src/Bahla.Tests/TestDataProvider.cs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
using System.Runtime.InteropServices.JavaScript;
|
||||||
|
using Bahla.Domain.Builders;
|
||||||
|
using Bahla.Domain.Entities;
|
||||||
|
using Bahla.Domain.Enums;
|
||||||
|
using Bahla.Domain.Types;
|
||||||
|
|
||||||
|
namespace Bahla.Tests;
|
||||||
|
|
||||||
|
public class TestDataProvider
|
||||||
|
{
|
||||||
|
public static readonly Identifier U1 = "d627dfe8-7896-483e-a78d-d5b5832a5543";
|
||||||
|
public static readonly Identifier U2 = "0d665df1-056d-4038-9d57-5999cb2bf72f";
|
||||||
|
public static readonly Identifier U3 = "066f7e1a-42ca-4139-9b2e-a6faeb880738";
|
||||||
|
public static readonly Identifier U4 = "081b9fe4-6c84-449b-9bdd-08c23b4b5e78";
|
||||||
|
|
||||||
|
public static Dictionary<Identifier, User> Users = new()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
U1,
|
||||||
|
User.Builder
|
||||||
|
.WithEmail("john.doe@mail.com")
|
||||||
|
.WithFirstname("John")
|
||||||
|
.WithLastname("Doe")
|
||||||
|
.WithRole(Role.Builder
|
||||||
|
.WithName("Animateur/Animatrice")
|
||||||
|
.WithValueMask(1 << 1)
|
||||||
|
.Build())
|
||||||
|
.WithGender(Gender.Male)
|
||||||
|
.WithBirthday(new DateTime(1990, 1, 1))
|
||||||
|
.WithJoinedOn(DateTime.Now
|
||||||
|
.AddDays(5))
|
||||||
|
.WithSalt([0x1, 0x2, 0x3, 0x4])
|
||||||
|
.WithVerifier([0x5, 0x6, 0x7, 0x8])
|
||||||
|
.Build()
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
U2,
|
||||||
|
User.Builder
|
||||||
|
.WithEmail("jane.doe@mail.com")
|
||||||
|
.WithFirstname("Jane")
|
||||||
|
.WithLastname("Doe")
|
||||||
|
.WithRole(Role.Builder
|
||||||
|
.WithName("Organisateur/Organisatrice")
|
||||||
|
.WithValueMask(1 << 2)
|
||||||
|
.Build())
|
||||||
|
.WithGender(Gender.Female)
|
||||||
|
.WithBirthday(new DateTime(1994, 3, 28))
|
||||||
|
.WithJoinedOn(DateTime.Now
|
||||||
|
.AddDays(10))
|
||||||
|
.WithSalt([0x10, 0x30, 0x40, 0x50])
|
||||||
|
.WithVerifier([0xA, 0xB, 0xC, 0xD])
|
||||||
|
.Build()
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
U3,
|
||||||
|
User.Builder
|
||||||
|
.WithEmail("alice.bob@mail.com")
|
||||||
|
.WithFirstname("Alice")
|
||||||
|
.WithLastname("Bob")
|
||||||
|
.WithRole(Role.Builder
|
||||||
|
.WithName("Usager/Usagère")
|
||||||
|
.WithValueMask(1 << 0)
|
||||||
|
.Build())
|
||||||
|
.WithGender(Gender.Female)
|
||||||
|
.WithBirthday(new DateTime(1998, 14, 04))
|
||||||
|
.WithJoinedOn(DateTime.Now
|
||||||
|
.AddMonths(2))
|
||||||
|
.WithSalt([0xB, 0xE, 0xE, 0xF])
|
||||||
|
.WithVerifier([0xC, 0xA, 0xF, 0xE, 0xE])
|
||||||
|
.Build()
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
U4,
|
||||||
|
User.Builder
|
||||||
|
.WithEmail("max.dupont@mail.com")
|
||||||
|
.WithFirstname("Max")
|
||||||
|
.WithLastname("Dupont")
|
||||||
|
.WithGender(Gender.Male)
|
||||||
|
.WithRole(Role.Builder
|
||||||
|
.WithName("Usager/Usagère")
|
||||||
|
.WithValueMask(1 << 0)
|
||||||
|
.Build())
|
||||||
|
.WithBirthday(new DateTime(1999, 12, 31))
|
||||||
|
.WithJoinedOn(DateTime.Now
|
||||||
|
.AddYears(2))
|
||||||
|
.WithSalt([0xF, 0xF])
|
||||||
|
.WithVerifier([0xE, 0xA, 0xF, 0xD])
|
||||||
|
.Build()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using Bahla.Domain.Types;
|
using Bahla.Domain.Types;
|
||||||
|
|
||||||
namespace Bahla.Tests.Entities
|
namespace Bahla.Tests.Types
|
||||||
{
|
{
|
||||||
internal class TypeIdentifierTests
|
internal class TypeIdentifierTests
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user