Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
8361351
Merge branch 'main' into HB-135
lk-code Nov 13, 2025
98c7b51
HB-135: add tests for frontend auth service
lk-code Nov 14, 2025
b18bc6d
HB-135: add tests for infohandler
lk-code Nov 14, 2025
f388202
HB_135: add mainlayout changes
lk-code Nov 14, 2025
18b36dc
HB-135: update mocks for recipemanagement and client code
lk-code Nov 16, 2025
921d7d4
HB-135: add new backend modules and endpoint logic
lk-code Nov 18, 2025
a410353
HB-135: fix unit tests for modules logic
lk-code Nov 18, 2025
c6450af
HB-135: fix unit tests for modules logic and improve search implement…
lk-code Nov 19, 2025
d87f1aa
HB-135: finalize search bsackend logic
lk-code Nov 19, 2025
26888a5
Merge branch 'main' into HB-135
lk-code Nov 21, 2025
e4115c4
HB-135: add recipe logic and basic ui loading
lk-code Nov 21, 2025
c975a9f
HB-135: add recipe logic for ef and backend
lk-code Nov 24, 2025
c52090a
HB-135: update nugets
lk-code Nov 24, 2025
e2156db
HB-135: Add User To Recipe Entity
lk-code Nov 24, 2025
8e8091e
HB-135: fix tests
lk-code Nov 24, 2025
0655668
HB-135: add ui for recipe overview
lk-code Nov 24, 2025
93cd71e
HB-135: add recipe additional logics
lk-code Nov 28, 2025
7fb6404
Merge branch 'main' into HB-135
lk-code Nov 28, 2025
67ca8d0
HB-135: add tests for JwtService
lk-code Dec 1, 2025
fa658c5
HB-135: optimize ui recipe logic
lk-code Dec 1, 2025
0b6dc33
HB-135: add recipe with name from meal recipe search dialog
lk-code Dec 1, 2025
82980f9
HB-135: add delete recipe from edit and view pages
lk-code Dec 1, 2025
57daa56
HB-135: add recipe getbyid endpoint for details
lk-code Dec 1, 2025
ecd79f3
HB-135: add detail recipe logic
lk-code Dec 1, 2025
66227a3
HB-135: add recipe edit ui and logic for description and servings
lk-code Dec 4, 2025
b3637b2
HB-135: add recipe ingredient ui
lk-code Dec 4, 2025
223173f
HB-135: add ui improvements for recipe edit
lk-code Dec 7, 2025
a8267e4
HB-135: add action buttons in footer
lk-code Dec 8, 2025
ad3cdf7
HB-135: add additional data to recipe entity
lk-code Dec 8, 2025
e544123
HB-135: add edit improvements
lk-code Dec 8, 2025
ae75549
HB-135: optimize recipe entity
lk-code Dec 8, 2025
10ee773
HB-135: add recipesteps position
lk-code Dec 9, 2025
23eaa6e
HB-135: add ef core logic for recipe and childs
lk-code Dec 9, 2025
7b3b456
HB-135: update nugets
lk-code Dec 9, 2025
aa88567
HB-135 - Updates NUnit3TestAdapter
lk-code Dec 9, 2025
a96b979
HB-135: fix recipe to ingredients
lk-code Dec 13, 2025
79a6960
HB-135 - Updates Scalar.AspNetCore
lk-code Dec 13, 2025
ae23ef5
HB-135: fix recipe name update
lk-code Dec 14, 2025
976a9d3
HB-135: updated client
lk-code Dec 14, 2025
10fb197
HB-135: update client and frontend interfaces
lk-code Dec 14, 2025
ab824e2
HB-135 - Updates Scalar.AspNetCore package
lk-code Dec 14, 2025
ac33719
HB-135: remove setup update local version mismatch check
lk-code Dec 15, 2025
a2cbe4b
HB-135 - Implements recipe edit components
lk-code Dec 16, 2025
74223a4
HB-135 - Makes recipe servings editable
lk-code Dec 16, 2025
7b36a0b
HB-135 - Makes ingredients and steps parameters
lk-code Dec 16, 2025
e7a407d
HB-135 - Refactors recipe servings component
lk-code Dec 16, 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
Binary file added assets/mocks/recipes-detail-01.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mocks/recipes-detail-step-01.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mocks/recipes-detail-step-02.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mocks/recipes-detail-step-03.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/mocks/recipes-overview-01.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 9 additions & 3 deletions generate-client.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ CLIENT_CLASS="BackendClient"
CLIENT_NAMESPACE="HomeBook.Client"
OPENAPI_FILE="./source/HomeBook.Backend/HomeBook.Backend.json"
CLIENT_OUTPUT_DIR="./source/HomeBook.Client"
CLIENT_CSPROJ="HomeBook.Client.csproj"

# build backend
# Clean output dir except the client csproj
find "${CLIENT_OUTPUT_DIR}" -mindepth 1 ! -name "${CLIENT_CSPROJ}" -exec rm -rf {} +

dotnet restore "${BACKEND_CSPROJ}"
dotnet build "${BACKEND_CSPROJ}" --no-restore -c Release
# build backend
dotnet build "${BACKEND_CSPROJ}" -c Debug
dotnet build "${BACKEND_CSPROJ}" -c Release

# install/update kiota
dotnet tool install --global Microsoft.OpenApi.Kiota
Expand All @@ -26,3 +29,6 @@ kiota generate \

echo "Client generation completed successfully!"
echo "Output directory: ${CLIENT_OUTPUT_DIR}"

# nuget restore client
dotnet restore "${CLIENT_OUTPUT_DIR}/${CLIENT_CSPROJ}"
55 changes: 30 additions & 25 deletions homebook.slnx
Original file line number Diff line number Diff line change
@@ -1,37 +1,42 @@
<Solution>
<Folder Name="/Backend/">
<Project Path="source\HomeBook.Backend.Abstractions\HomeBook.Backend.Abstractions.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.DTOs\HomeBook.Backend.DTOs.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend\HomeBook.Backend.csproj" Type="Classic C#" />
<Project Path="source/HomeBook.Backend.Modules.Abstractions/HomeBook.Backend.Modules.Abstractions.csproj" />
<Project Path="source\HomeBook.Backend.Abstractions\HomeBook.Backend.Abstractions.csproj" />
<Project Path="source\HomeBook.Backend.DTOs\HomeBook.Backend.DTOs.csproj" />
<Project Path="source\HomeBook.Backend\HomeBook.Backend.csproj" />
</Folder>
<Folder Name="/Backend/Core/">
<Project Path="source\HomeBook.Backend.Core.Account\HomeBook.Backend.Core.Account.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.Core.DataProvider\HomeBook.Backend.Core.DataProvider.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.Core.Finances\HomeBook.Backend.Core.Finances.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.Core.Kitchen\HomeBook.Backend.Core.Kitchen.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.Core.Licenses\HomeBook.Backend.Core.Licenses.csproj" Type="Classic C#" />
<Project Path="source\Homebook.Backend.Core.Setup\Homebook.Backend.Core.Setup.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.Core\HomeBook.Backend.Core.csproj" Type="Classic C#" />
<Project Path="source/HomeBook.Backend.Core.Modules/HomeBook.Backend.Core.Modules.csproj" />
<Project Path="source/HomeBook.Backend.Core.Search/HomeBook.Backend.Core.Search.csproj" />
<Project Path="source\HomeBook.Backend.Core.Account\HomeBook.Backend.Core.Account.csproj" />
<Project Path="source\HomeBook.Backend.Core.DataProvider\HomeBook.Backend.Core.DataProvider.csproj" />
<Project Path="source\HomeBook.Backend.Core.Licenses\HomeBook.Backend.Core.Licenses.csproj" />
<Project Path="source\Homebook.Backend.Core.Setup\Homebook.Backend.Core.Setup.csproj" />
<Project Path="source\HomeBook.Backend.Core\HomeBook.Backend.Core.csproj" />
</Folder>
<Folder Name="/Backend/Data/">
<Project Path="source\HomeBook.Backend.Data.Mysql\HomeBook.Backend.Data.Mysql.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.Data.PostgreSql\HomeBook.Backend.Data.PostgreSql.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.Data.Sqlite\HomeBook.Backend.Data.Sqlite.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.Data\HomeBook.Backend.Data.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Backend.Data.Mysql\HomeBook.Backend.Data.Mysql.csproj" />
<Project Path="source\HomeBook.Backend.Data.PostgreSql\HomeBook.Backend.Data.PostgreSql.csproj" />
<Project Path="source\HomeBook.Backend.Data.Sqlite\HomeBook.Backend.Data.Sqlite.csproj" />
<Project Path="source\HomeBook.Backend.Data\HomeBook.Backend.Data.csproj" />
</Folder>
<Folder Name="/Backend/Modules/">
<Project Path="source/HomeBook.Backend.Module.Finances/HomeBook.Backend.Module.Finances.csproj" />
<Project Path="source/HomeBook.Backend.Module.Kitchen/HomeBook.Backend.Module.Kitchen.csproj" />
</Folder>
<Folder Name="/Frontend/">
<Project Path="source\HomeBook.Client\HomeBook.Client.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Frontend.Abstractions\HomeBook.Frontend.Abstractions.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Frontend.Core\HomeBook.Frontend.Core.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Frontend.Modules.Abstractions\HomeBook.Frontend.Modules.Abstractions.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Frontend.Services\HomeBook.Frontend.Services.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Frontend.UI\HomeBook.Frontend.UI.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Frontend\HomeBook.Frontend.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Client\HomeBook.Client.csproj" />
<Project Path="source\HomeBook.Frontend.Abstractions\HomeBook.Frontend.Abstractions.csproj" />
<Project Path="source\HomeBook.Frontend.Core\HomeBook.Frontend.Core.csproj" />
<Project Path="source\HomeBook.Frontend.Modules.Abstractions\HomeBook.Frontend.Modules.Abstractions.csproj" />
<Project Path="source\HomeBook.Frontend.Services\HomeBook.Frontend.Services.csproj" />
<Project Path="source\HomeBook.Frontend.UI\HomeBook.Frontend.UI.csproj" />
<Project Path="source\HomeBook.Frontend\HomeBook.Frontend.csproj" />
</Folder>
<Folder Name="/Frontend/Modules/">
<Project Path="source\HomeBook.Frontend.Module.Finances\HomeBook.Frontend.Module.Finances.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Frontend.Module.Kitchen\HomeBook.Frontend.Module.Kitchen.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Frontend.Module.PlatformInfo\HomeBook.Frontend.Module.PlatformInfo.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.Frontend.Module.Finances\HomeBook.Frontend.Module.Finances.csproj" />
<Project Path="source\HomeBook.Frontend.Module.Kitchen\HomeBook.Frontend.Module.Kitchen.csproj" />
<Project Path="source\HomeBook.Frontend.Module.PlatformInfo\HomeBook.Frontend.Module.PlatformInfo.csproj" />
</Folder>
<Folder Name="/Solution/">
<File Path="LICENSE" />
Expand Down Expand Up @@ -63,6 +68,6 @@
<File Path=".github\workflows\pull-request.yml" />
</Folder>
<Folder Name="/Tests/">
<Project Path="source\HomeBook.UnitTests\HomeBook.UnitTests.csproj" Type="Classic C#" />
<Project Path="source\HomeBook.UnitTests\HomeBook.UnitTests.csproj" />
</Folder>
</Solution>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace HomeBook.Backend.Abstractions.Contracts;

public interface IEndpointDataAccessor
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace HomeBook.Backend.Abstractions.Contracts;

public interface ISearchAggregationResult
{
public string ModuleKey { get; }
public int TotalCount { get; }
public IEnumerable<ISearchResultItem> Items { get; }
}
19 changes: 19 additions & 0 deletions source/HomeBook.Backend.Abstractions/Contracts/ISearchProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace HomeBook.Backend.Abstractions.Contracts;

/// <summary>
///
/// </summary>
public interface ISearchProvider
{
/// <summary>
///
/// </summary>
/// <param name="query"></param>
/// <param name="userId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<IReadOnlyList<ISearchAggregationResult>>
SearchAsync(string query,
Guid userId,
CancellationToken cancellationToken = default);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace HomeBook.Backend.Abstractions.Contracts;

public interface ISearchRegistrationFactory
{
ISearchProvider CreateSearchProvider();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace HomeBook.Backend.Abstractions.Contracts;

public interface ISearchRegistrationInitiator
{
void AddModule(string moduleId);
void AddServiceProvider(IServiceProvider serviceProvider);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace HomeBook.Backend.Abstractions.Contracts;

public interface ISearchResultItem
{
string Title { get; }
string? Description { get; }
string Url { get; }
string Icon { get; }
string Color { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,13 @@ Task<bool> ContainsUserAsync(string username,
Task UpdateAdminFlag(Guid userId,
bool isAdmin,
CancellationToken cancellationToken);

/// <summary>
///
/// </summary>
/// <param name="userId"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
Task<UserInfo?> GetUserByIdAsync(Guid userId,
CancellationToken cancellationToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.10" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.11" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.0" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.11" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.14.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.14.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.15.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.15.0" />
</ItemGroup>

</Project>
40 changes: 24 additions & 16 deletions source/HomeBook.Backend.Core.Account/JwtService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@ namespace HomeBook.Backend.Core.Account;
/// </summary>
public class JwtService(IConfiguration configuration) : IJwtService
{
private readonly string _secretKey = configuration["Jwt:SecretKey"] ?? throw new InvalidOperationException("JWT SecretKey is required");
private readonly string _issuer = configuration["Jwt:Issuer"] ?? "HomeBook";
private readonly string _audience = configuration["Jwt:Audience"] ?? "HomeBook";
private readonly int _expirationMinutes = int.Parse(configuration["Jwt:ExpirationMinutes"] ?? "60");
private readonly string _secretKey = configuration["Jwt:SecretKey"]
?? throw new InvalidOperationException("JWT SecretKey is required");

private readonly string _issuer = configuration["Jwt:Issuer"]
?? "HomeBook";

private readonly string _audience = configuration["Jwt:Audience"]
?? "HomeBook";

private readonly int _expirationMinutes = int.Parse(configuration["Jwt:ExpirationMinutes"]
?? "60");

/// <inheritdoc />
public JwtTokenResult GenerateToken(Guid userId, string username)
{
return GenerateToken(userId, username, false);
}
public JwtTokenResult GenerateToken(Guid userId, string username) => GenerateToken(userId, username, false);

/// <inheritdoc />
public JwtTokenResult GenerateToken(Guid userId, string username, bool isAdmin)
Expand All @@ -36,14 +40,18 @@ public JwtTokenResult GenerateToken(Guid userId, string username, bool isAdmin)
[
new(ClaimTypes.NameIdentifier, userId.ToString()),
new(ClaimTypes.Name, username),
new(ClaimTypes.Role, isAdmin ? "Admin" : "User"),
new("IsAdmin", isAdmin.ToString(), ClaimValueTypes.Boolean),
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new(JwtRegisteredClaimNames.Iat,
new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds().ToString(),
ClaimValueTypes.Integer64)
];

if (isAdmin)
{
claims = claims.Append(new Claim(ClaimTypes.Role, isAdmin ? "Admin" : "User")).ToArray();
claims = claims.Append(new Claim("IsAdmin", isAdmin.ToString(), ClaimValueTypes.Boolean)).ToArray();
}

JwtSecurityToken token = new(
issuer: _issuer,
audience: _audience,
Expand Down Expand Up @@ -71,8 +79,8 @@ public bool ValidateToken(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes(_secretKey);
JwtSecurityTokenHandler tokenHandler = new();
byte[] key = Encoding.UTF8.GetBytes(_secretKey);

tokenHandler.ValidateToken(token,
new TokenValidationParameters
Expand Down Expand Up @@ -101,10 +109,10 @@ public bool ValidateToken(string token)
{
try
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.UTF8.GetBytes(_secretKey);
JwtSecurityTokenHandler tokenHandler = new();
byte[] key = Encoding.UTF8.GetBytes(_secretKey);

var principal = tokenHandler.ValidateToken(token,
ClaimsPrincipal? principal = tokenHandler.ValidateToken(token,
new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
Expand All @@ -118,7 +126,7 @@ public bool ValidateToken(string token)
},
out SecurityToken validatedToken);

var userIdClaim = principal.FindFirst(ClaimTypes.NameIdentifier);
Claim? userIdClaim = principal.FindFirst(ClaimTypes.NameIdentifier);
if (userIdClaim != null && Guid.TryParse(userIdClaim.Value, out Guid userId))
{
return userId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@

<ItemGroup>
<ProjectReference Include="..\HomeBook.Backend.Data\HomeBook.Backend.Data.csproj"/>
<ProjectReference Include="..\HomeBook.Frontend.Abstractions\HomeBook.Frontend.Abstractions.csproj"/>
</ItemGroup>

<ItemGroup>
<PackageReference Include="FluentValidation" Version="12.1.0" />
<PackageReference Include="FluentValidation" Version="12.1.1" />
</ItemGroup>

</Project>
6 changes: 6 additions & 0 deletions source/HomeBook.Backend.Core.DataProvider/UserProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,10 @@ public Task UpdateAdminFlag(Guid userId,
},
cancellationToken);
}

/// <inheritdoc />
public async Task<UserInfo?> GetUserByIdAsync(Guid userId,
CancellationToken cancellationToken) =>
(await userRepository.GetUserByIdAsync(userId,
cancellationToken))?.ToUserInfo();
}

This file was deleted.

This file was deleted.

Loading
Loading