零度框架 1.0 版本正式发布,共 184 项改进。

This commit is contained in:
hello 2024-05-31 12:28:02 +08:00
parent c14a872b77
commit baf06cd88f
182 changed files with 2537 additions and 1613 deletions

View File

@ -1,4 +1,5 @@
Microsoft Visual Studio Solution File, Format Version 12.00 
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 17
VisualStudioVersion = 17.9.34414.90 VisualStudioVersion = 17.9.34414.90
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
@ -26,6 +27,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloShop.ProductService.Un
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloShop.ProductService.FunctionalTests", "tests\HelloShop.ProductService.FunctionalTests\HelloShop.ProductService.FunctionalTests.csproj", "{45932B7F-6ED0-40F3-AA2C-F14A844FEE18}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HelloShop.ProductService.FunctionalTests", "tests\HelloShop.ProductService.FunctionalTests\HelloShop.ProductService.FunctionalTests.csproj", "{45932B7F-6ED0-40F3-AA2C-F14A844FEE18}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloShop.HybridApp", "src\HelloShop.HybridApp\HelloShop.HybridApp.csproj", "{E58F82E2-2E48-459B-A40E-497F24FC6DC1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelloShop.FunctionalTests", "tests\HelloShop.FunctionalTests\HelloShop.FunctionalTests.csproj", "{6BAA9747-E0D0-41B9-8A1B-88B777498C43}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -72,6 +77,16 @@ Global
{45932B7F-6ED0-40F3-AA2C-F14A844FEE18}.Debug|Any CPU.Build.0 = Debug|Any CPU {45932B7F-6ED0-40F3-AA2C-F14A844FEE18}.Debug|Any CPU.Build.0 = Debug|Any CPU
{45932B7F-6ED0-40F3-AA2C-F14A844FEE18}.Release|Any CPU.ActiveCfg = Release|Any CPU {45932B7F-6ED0-40F3-AA2C-F14A844FEE18}.Release|Any CPU.ActiveCfg = Release|Any CPU
{45932B7F-6ED0-40F3-AA2C-F14A844FEE18}.Release|Any CPU.Build.0 = Release|Any CPU {45932B7F-6ED0-40F3-AA2C-F14A844FEE18}.Release|Any CPU.Build.0 = Release|Any CPU
{E58F82E2-2E48-459B-A40E-497F24FC6DC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E58F82E2-2E48-459B-A40E-497F24FC6DC1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E58F82E2-2E48-459B-A40E-497F24FC6DC1}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{E58F82E2-2E48-459B-A40E-497F24FC6DC1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E58F82E2-2E48-459B-A40E-497F24FC6DC1}.Release|Any CPU.Build.0 = Release|Any CPU
{E58F82E2-2E48-459B-A40E-497F24FC6DC1}.Release|Any CPU.Deploy.0 = Release|Any CPU
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6BAA9747-E0D0-41B9-8A1B-88B777498C43}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -87,6 +102,8 @@ Global
{02EBA5AD-84B4-4AF4-B519-72061C08800D} = {1AD03316-A743-4E9D-B3BC-FB9499D15141} {02EBA5AD-84B4-4AF4-B519-72061C08800D} = {1AD03316-A743-4E9D-B3BC-FB9499D15141}
{2022279A-E39F-4489-82AE-39AC53C594C9} = {29BE158E-825E-48AB-A02D-4E537A5DC502} {2022279A-E39F-4489-82AE-39AC53C594C9} = {29BE158E-825E-48AB-A02D-4E537A5DC502}
{45932B7F-6ED0-40F3-AA2C-F14A844FEE18} = {29BE158E-825E-48AB-A02D-4E537A5DC502} {45932B7F-6ED0-40F3-AA2C-F14A844FEE18} = {29BE158E-825E-48AB-A02D-4E537A5DC502}
{E58F82E2-2E48-459B-A40E-497F24FC6DC1} = {1AD03316-A743-4E9D-B3BC-FB9499D15141}
{6BAA9747-E0D0-41B9-8A1B-88B777498C43} = {29BE158E-825E-48AB-A02D-4E537A5DC502}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {845545A8-2006-46C3-ABD7-5BDF63F3858C} SolutionGuid = {845545A8-2006-46C3-ABD7-5BDF63F3858C}

View File

@ -1,4 +1,7 @@
using HelloShop.ApiService.Services; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ApiService.Services;
using HelloShop.ServiceDefaults.Permissions; using HelloShop.ServiceDefaults.Permissions;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;

View File

@ -1,4 +1,7 @@
using Microsoft.AspNetCore.Mvc; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.AspNetCore.Mvc;
namespace HelloShop.ApiService.Controllers; namespace HelloShop.ApiService.Controllers;

View File

@ -1,10 +1,13 @@
using HelloShop.ApiService.Infrastructure; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ApiService.Infrastructure;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Swashbuckle.AspNetCore.SwaggerUI; using Swashbuckle.AspNetCore.SwaggerUI;
namespace HelloShop.ApiService.Extensions; namespace HelloShop.ApiService.Extensions;
public class OpenApiConfigureOptions(IConfiguredServiceEndPointResolver serviceResolver, HttpClient httpClient) : IConfigureOptions<SwaggerUIOptions> public class OpenApiConfigureOptions(IConfiguredServiceEndPointResolver serviceResolver, HttpClient httpClient, ILogger<OpenApiConfigureOptions> logger) : IConfigureOptions<SwaggerUIOptions>
{ {
public void Configure(SwaggerUIOptions options) public void Configure(SwaggerUIOptions options)
{ {
@ -16,21 +19,27 @@ public class OpenApiConfigureOptions(IConfiguredServiceEndPointResolver serviceR
{ {
UriBuilder uriBuilder = new(endPoint) { Path = "swagger/v1/swagger.json" }; UriBuilder uriBuilder = new(endPoint) { Path = "swagger/v1/swagger.json" };
HttpResponseMessage response = httpClient.GetAsync(uriBuilder.Uri).GetAwaiter().GetResult(); try
if (response.IsSuccessStatusCode)
{ {
urlDescriptors.Add(new UrlDescriptor HttpResponseMessage response = httpClient.GetAsync(uriBuilder.Uri).GetAwaiter().GetResult();
if (response.IsSuccessStatusCode)
{ {
Url = uriBuilder.Uri.ToString(), urlDescriptors.Add(new UrlDescriptor
Name = serviceEndpoint.ServiceName {
}); Url = uriBuilder.Uri.ToString(),
break; Name = serviceEndpoint.ServiceName
});
break;
}
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to get swagger endpoint for {ServiceName}", serviceEndpoint.ServiceName);
} }
} }
} }
options.ConfigObject.Urls = urlDescriptors; options.ConfigObject.Urls = urlDescriptors;
options.SwaggerEndpoint("v1/swagger.json", "apiservice"); options.SwaggerEndpoint("v1/swagger.json", "apiservice");
} }
} }

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
@ -9,7 +9,6 @@
<ProjectReference Include="..\HelloShop.ServiceDefaults\HelloShop.ServiceDefaults.csproj" /> <ProjectReference Include="..\HelloShop.ServiceDefaults\HelloShop.ServiceDefaults.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery.Yarp" Version="9.0.0-preview.3.24210.17" /> <PackageReference Include="Microsoft.Extensions.ServiceDiscovery.Yarp" Version="8.0.1" />
<PackageReference Include="Yarp.ReverseProxy" Version="2.1.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,4 +1,7 @@
namespace HelloShop.ApiService.Infrastructure // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.ApiService.Infrastructure
{ {
public class ConfiguredServiceEndPoint public class ConfiguredServiceEndPoint
{ {

View File

@ -1,10 +1,12 @@
 // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Extensions.ServiceDiscovery.Abstractions; using Microsoft.Extensions.ServiceDiscovery;
namespace HelloShop.ApiService.Infrastructure; namespace HelloShop.ApiService.Infrastructure;
public class ConfiguredServiceEndPointResolver(IConfiguration configuration, IOptions<ConfigurationServiceEndPointResolverOptions> resolverOptions) : IConfiguredServiceEndPointResolver public class ConfiguredServiceEndPointResolver(IConfiguration configuration, IOptions<ConfigurationServiceEndpointProviderOptions> resolverOptions) : IConfiguredServiceEndPointResolver
{ {
private readonly Lazy<IReadOnlyCollection<ConfiguredServiceEndPoint>> _serviceEndPoints = new(() => private readonly Lazy<IReadOnlyCollection<ConfiguredServiceEndPoint>> _serviceEndPoints = new(() =>
{ {

View File

@ -1,4 +1,7 @@
using Yarp.ReverseProxy.Configuration; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Yarp.ReverseProxy.Configuration;
using Yarp.ReverseProxy.LoadBalancing; using Yarp.ReverseProxy.LoadBalancing;
namespace HelloShop.ApiService.Infrastructure; namespace HelloShop.ApiService.Infrastructure;

View File

@ -1,4 +1,7 @@
namespace HelloShop.ApiService.Infrastructure; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.ApiService.Infrastructure;
public interface IConfiguredServiceEndPointResolver public interface IConfiguredServiceEndPointResolver
{ {

View File

@ -1,4 +1,7 @@
using Yarp.ReverseProxy.Configuration; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Yarp.ReverseProxy.Configuration;
namespace HelloShop.ApiService.Infrastructure; namespace HelloShop.ApiService.Infrastructure;

View File

@ -1,10 +1,13 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ApiService.Extensions;
using HelloShop.ApiService.Infrastructure; using HelloShop.ApiService.Infrastructure;
using Yarp.ReverseProxy.Configuration; using HelloShop.ApiService.Services;
using HelloShop.ServiceDefaults.Extensions; using HelloShop.ServiceDefaults.Extensions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Swashbuckle.AspNetCore.SwaggerUI; using Swashbuckle.AspNetCore.SwaggerUI;
using HelloShop.ApiService.Extensions; using Yarp.ReverseProxy.Configuration;
using HelloShop.ApiService.Services;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);

View File

@ -6,10 +6,20 @@
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "swagger", "launchUrl": "swagger",
"applicationUrl": "http://localhost:5391", "applicationUrl": "http://localhost:8001",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:8101;http://localhost:8001",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
} }
} }
} }

View File

@ -1,4 +1,7 @@
using HelloShop.ServiceDefaults.Permissions; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ServiceDefaults.Permissions;
namespace HelloShop.ApiService.Services; namespace HelloShop.ApiService.Services;

View File

@ -1,4 +1,7 @@
using HelloShop.ApiService.Infrastructure; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ApiService.Infrastructure;
using HelloShop.ServiceDefaults.Permissions; using HelloShop.ServiceDefaults.Permissions;
namespace HelloShop.ApiService.Services; namespace HelloShop.ApiService.Services;
@ -13,7 +16,7 @@ public class PermissionService(HttpClient httpClient, IConfiguredServiceEndPoint
IReadOnlyCollection<ConfiguredServiceEndPoint> serviceEndPoints = await serviceEndPointResolver.GetConfiguredServiceEndpointsAsync(cancellationToken); IReadOnlyCollection<ConfiguredServiceEndPoint> serviceEndPoints = await serviceEndPointResolver.GetConfiguredServiceEndpointsAsync(cancellationToken);
await Parallel.ForEachAsync(serviceEndPoints, new ParallelOptions{ CancellationToken= cancellationToken}, async (serviceEndPoint, cancelToken) => await Parallel.ForEachAsync(serviceEndPoints, new ParallelOptions { CancellationToken = cancellationToken }, async (serviceEndPoint, cancelToken) =>
{ {
UriBuilder uriBuilder = new(serviceEndPoint.ServiceName) { Path = "api/Permissions/PermissionDefinitions" }; UriBuilder uriBuilder = new(serviceEndPoint.ServiceName) { Path = "api/Permissions/PermissionDefinitions" };

View File

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost> <IsAspireHost>true</IsAspireHost>
@ -15,6 +15,6 @@
<ProjectReference Include="..\HelloShop.WebApp\HelloShop.WebApp.csproj" /> <ProjectReference Include="..\HelloShop.WebApp\HelloShop.WebApp.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.0.0-preview.3.24210.17" /> <PackageReference Include="Aspire.Hosting.AppHost" Version="8.0.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -1,8 +1,11 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
var builder = DistributedApplication.CreateBuilder(args); var builder = DistributedApplication.CreateBuilder(args);
var identityService = builder.AddProject<Projects.HelloShop_IdentityService>("identityservice"); var identityService = builder.AddProject<Projects.HelloShop_IdentityService>("identityservice");
var orderingService=builder.AddProject<Projects.HelloShop_OrderingService>("orderingservice").WithReference(identityService); var orderingService = builder.AddProject<Projects.HelloShop_OrderingService>("orderingservice").WithReference(identityService);
var productService = builder.AddProject<Projects.HelloShop_ProductService>("productservice").WithReference(identityService); var productService = builder.AddProject<Projects.HelloShop_ProductService>("productservice").WithReference(identityService);

View File

@ -1,16 +1,29 @@
{ {
"$schema": "http://json.schemastore.org/launchsettings.json", "$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": { "profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:8100;http://localhost:8000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21017",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22002"
}
},
"http": { "http": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"applicationUrl": "http://localhost:15016", "applicationUrl": "http://localhost:8000",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development", "ASPNETCORE_ENVIRONMENT": "Development",
"DOTNET_ENVIRONMENT": "Development", "DOTNET_ENVIRONMENT": "Development",
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:16173" "DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19004",
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20155"
} }
} }
} }
} }

View File

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
@ -8,7 +8,7 @@
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" /> <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.62.0" /> <PackageReference Include="Grpc.AspNetCore" Version="2.63.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\HelloShop.ServiceDefaults\HelloShop.ServiceDefaults.csproj" /> <ProjectReference Include="..\HelloShop.ServiceDefaults\HelloShop.ServiceDefaults.csproj" />

View File

@ -1,4 +1,8 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.BasketService.Services; using HelloShop.BasketService.Services;
using HelloShop.ServiceDefaults.Extensions;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);

View File

@ -5,7 +5,7 @@
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": false, "launchBrowser": false,
"applicationUrl": "http://localhost:5079", "applicationUrl": "http://localhost:8004",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
@ -14,10 +14,10 @@
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": false, "launchBrowser": false,
"applicationUrl": "https://localhost:7022;http://localhost:5079", "applicationUrl": "https://localhost:8104;http://localhost:8004",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
} }
} }
} }

View File

@ -1,5 +1,7 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Grpc.Core; using Grpc.Core;
using HelloShop.BasketService;
namespace HelloShop.BasketService.Services; namespace HelloShop.BasketService.Services;

View File

@ -5,10 +5,5 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"AllowedHosts": "*", "AllowedHosts": "*"
"Kestrel": { }
"EndpointDefaults": {
"Protocols": "Http2"
}
}
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloShop.HybridApp" xmlns:local="clr-namespace:HelloShop.HybridApp"

View File

@ -1,4 +1,7 @@
namespace HelloShop.HybridApp // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.HybridApp
{ {
public partial class App : Application public partial class App : Application
{ {

View File

@ -1,6 +1,6 @@
<Router AppAssembly="@typeof(MauiProgram).Assembly"> <Router AppAssembly="@typeof(MauiProgram).Assembly">
<Found Context="routeData"> <Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Components.Layout.MainLayout)" /> <RouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" /> <FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found> </Found>
</Router> </Router>

View File

@ -1,53 +1,67 @@
<Project Sdk="Microsoft.NET.Sdk.Razor"> <Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst</TargetFrameworks> <PropertyGroup>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks> <TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET --> <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
<!-- <TargetFrameworks>$(TargetFrameworks);net9.0-tizen</TargetFrameworks> --> <!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- Note for MacCatalyst: <!-- <TargetFrameworks>$(TargetFrameworks);net8.0-tizen</TargetFrameworks> -->
<!-- Note for MacCatalyst:
The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64. The default runtime is maccatalyst-x64, except in Release config, in which case the default is maccatalyst-x64;maccatalyst-arm64.
When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>. When specifying both architectures, use the plural <RuntimeIdentifiers> instead of the singular <RuntimeIdentifier>.
The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated; The Mac App Store will NOT accept apps with ONLY maccatalyst-arm64 indicated;
either BOTH runtimes must be indicated or ONLY macatalyst-x64. --> either BOTH runtimes must be indicated or ONLY macatalyst-x64. -->
<!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> --> <!-- For example: <RuntimeIdentifiers>maccatalyst-x64;maccatalyst-arm64</RuntimeIdentifiers> -->
<OutputType>Exe</OutputType>
<RootNamespace>HelloShop.HybridApp</RootNamespace> <OutputType>Exe</OutputType>
<UseMaui>true</UseMaui> <RootNamespace>HelloShop.HybridApp</RootNamespace>
<SingleProject>true</SingleProject> <UseMaui>true</UseMaui>
<ImplicitUsings>enable</ImplicitUsings> <SingleProject>true</SingleProject>
<EnableDefaultCssItems>false</EnableDefaultCssItems> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <EnableDefaultCssItems>false</EnableDefaultCssItems>
<!-- Display name --> <Nullable>enable</Nullable>
<ApplicationTitle>HelloShop.HybridApp</ApplicationTitle>
<!-- App Identifier --> <!-- Display name -->
<ApplicationId>com.companyname.helloshop.hybridapp</ApplicationId> <ApplicationTitle>HelloShop.HybridApp</ApplicationTitle>
<!-- Versions -->
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> <!-- App Identifier -->
<ApplicationVersion>1</ApplicationVersion> <ApplicationId>com.companyname.helloshop.hybridapp</ApplicationId>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion> <!-- Versions -->
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">24.0</SupportedOSPlatformVersion> <ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion> <ApplicationVersion>1</ApplicationVersion>
<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">14.2</SupportedOSPlatformVersion>
</PropertyGroup> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">14.0</SupportedOSPlatformVersion>
<ItemGroup> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">24.0</SupportedOSPlatformVersion>
<!-- App Icon --> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
<MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" /> <TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
<!-- Splash Screen --> <SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
<MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" /> </PropertyGroup>
<!-- Images -->
<MauiImage Include="Resources\Images\*" /> <ItemGroup>
<MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" /> <!-- App Icon -->
<!-- Custom Fonts --> <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
<MauiFont Include="Resources\Fonts\*" />
<!-- Raw Assets (also remove the "Resources\Raw" prefix) --> <!-- Splash Screen -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> <MauiSplashScreen Include="Resources\Splash\splash.svg" Color="#512BD4" BaseSize="128,128" />
</ItemGroup>
<ItemGroup> <!-- Images -->
<PackageReference Include="Microsoft.Maui.Controls" Version="$(MauiVersion)" /> <MauiImage Include="Resources\Images\*" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="$(MauiVersion)" /> <MauiImage Update="Resources\Images\dotnet_bot.svg" BaseSize="168,208" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="$(MauiVersion)" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.0-preview.1.24080.9" /> <!-- Custom Fonts -->
</ItemGroup> <MauiFont Include="Resources\Fonts\*" />
</Project>
<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.40" />
<PackageReference Include="Microsoft.Maui.Controls.Compatibility" Version="8.0.40" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebView.Maui" Version="8.0.40" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
</ItemGroup>
</Project>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloShop.HybridApp" xmlns:local="clr-namespace:HelloShop.HybridApp"
@ -7,7 +7,7 @@
<BlazorWebView x:Name="blazorWebView" HostPage="wwwroot/index.html"> <BlazorWebView x:Name="blazorWebView" HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents> <BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Routes}" /> <RootComponent Selector="#app" ComponentType="{x:Type local:Components.Routes}" />
</BlazorWebView.RootComponents> </BlazorWebView.RootComponents>
</BlazorWebView> </BlazorWebView>

View File

@ -1,4 +1,7 @@
namespace HelloShop.HybridApp // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.HybridApp
{ {
public partial class MainPage : ContentPage public partial class MainPage : ContentPage
{ {

View File

@ -1,4 +1,7 @@
using Microsoft.Extensions.Logging; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.Extensions.Logging;
namespace HelloShop.HybridApp namespace HelloShop.HybridApp
{ {
@ -17,8 +20,8 @@ namespace HelloShop.HybridApp
builder.Services.AddMauiBlazorWebView(); builder.Services.AddMauiBlazorWebView();
#if DEBUG #if DEBUG
builder.Services.AddBlazorWebViewDeveloperTools(); builder.Services.AddBlazorWebViewDeveloperTools();
builder.Logging.AddDebug(); builder.Logging.AddDebug();
#endif #endif
return builder.Build(); return builder.Build();

View File

@ -1,6 +1,8 @@
using Android.App; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Android.App;
using Android.Content.PM; using Android.Content.PM;
using Android.OS;
namespace HelloShop.HybridApp namespace HelloShop.HybridApp
{ {

View File

@ -1,4 +1,7 @@
using Android.App; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Android.App;
using Android.Runtime; using Android.Runtime;
namespace HelloShop.HybridApp namespace HelloShop.HybridApp

View File

@ -1,4 +1,7 @@
using Foundation; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Foundation;
namespace HelloShop.HybridApp namespace HelloShop.HybridApp
{ {

View File

@ -1,4 +1,6 @@
using ObjCRuntime; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using UIKit; using UIKit;
namespace HelloShop.HybridApp namespace HelloShop.HybridApp

View File

@ -1,3 +1,6 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.Maui; using Microsoft.Maui;
using Microsoft.Maui.Hosting; using Microsoft.Maui.Hosting;
using System; using System;

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest package="maui-application-id-placeholder" version="0.0.0" api-version="7" xmlns="http://tizen.org/ns/packages"> <manifest package="maui-application-id-placeholder" version="0.0.0" api-version="8" xmlns="http://tizen.org/ns/packages">
<profile name="common" /> <profile name="common" />
<ui-application appid="maui-application-id-placeholder" exec="HelloShop.HybridApp.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single"> <ui-application appid="maui-application-id-placeholder" exec="HelloShop.HybridApp.dll" multiple="false" nodisplay="false" taskmanage="true" type="dotnet" launch_mode="single">
<label>maui-application-title-placeholder</label> <label>maui-application-title-placeholder</label>

View File

@ -1,4 +1,4 @@
<maui:MauiWinUIApplication <maui:MauiWinUIApplication
x:Class="HelloShop.HybridApp.WinUI.App" x:Class="HelloShop.HybridApp.WinUI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

View File

@ -1,4 +1,5 @@
using Microsoft.UI.Xaml; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
// To learn more about WinUI, the WinUI project structure, // To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info. // and more about our project templates, see: http://aka.ms/winui-project-info.

View File

@ -8,7 +8,7 @@
<Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" /> <Identity Name="maui-package-name-placeholder" Publisher="CN=User Name" Version="0.0.0.0" />
<mp:PhoneIdentity PhoneProductId="5A3B6515-D86E-4266-8B27-B8E3D7427D85" PhonePublisherId="00000000-0000-0000-0000-000000000000"/> <mp:PhoneIdentity PhoneProductId="FD31B999-5B05-455A-86DB-F866D70C7A97" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties> <Properties>
<DisplayName>$placeholder$</DisplayName> <DisplayName>$placeholder$</DisplayName>

View File

@ -1,4 +1,7 @@
using Foundation; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Foundation;
namespace HelloShop.HybridApp namespace HelloShop.HybridApp
{ {

View File

@ -1,4 +1,6 @@
using ObjCRuntime; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using UIKit; using UIKit;
namespace HelloShop.HybridApp namespace HelloShop.HybridApp

View File

@ -4,7 +4,7 @@ is automatically handled by the following `MauiAsset` Build Action within your `
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" /> <MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
These files will be deployed with you package and will be accessible using Essentials: These files will be deployed with your package and will be accessible using Essentials:
async Task LoadMauiAsset() async Task LoadMauiAsset()
{ {

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService;
public class CustomJwtBearerDefaults public class CustomJwtBearerDefaults
{ {

View File

@ -1,4 +1,7 @@
using HelloShop.IdentityService.Entities; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.IdentityService.Entities;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;

View File

@ -1,4 +1,7 @@
using Microsoft.AspNetCore.Authentication; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.BearerToken; using Microsoft.AspNetCore.Authentication.BearerToken;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;

View File

@ -1,4 +1,7 @@
using Microsoft.AspNetCore.Authentication; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.AspNetCore.Authentication;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
namespace HelloShop.IdentityService; namespace HelloShop.IdentityService;

View File

@ -1,4 +1,7 @@
using HelloShop.ServiceDefaults.Constants; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ServiceDefaults.Constants;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System.Security.Claims; using System.Security.Claims;

View File

@ -1,4 +1,7 @@
using HelloShop.IdentityService.Entities; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.IdentityService.Entities;
using HelloShop.IdentityService.EntityFrameworks; using HelloShop.IdentityService.EntityFrameworks;
using HelloShop.ServiceDefaults.Authorization; using HelloShop.ServiceDefaults.Authorization;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;

View File

@ -1,7 +1,9 @@
using AutoMapper; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using AutoMapper;
using HelloShop.IdentityService.Entities; using HelloShop.IdentityService.Entities;
using HelloShop.IdentityService.Models.Users; using HelloShop.IdentityService.Models.Users;
using Microsoft.Extensions.Options;
namespace HelloShop.IdentityService.AutoMapper; namespace HelloShop.IdentityService.AutoMapper;

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService.Constants // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService.Constants
{ {
public class DbConstants public class DbConstants
{ {

View File

@ -1,4 +1,7 @@
using HelloShop.IdentityService.Entities; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.IdentityService.Entities;
using Microsoft.AspNetCore.Authentication.BearerToken; using Microsoft.AspNetCore.Authentication.BearerToken;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Http.HttpResults;

View File

@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Mvc; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using System.Globalization;
using System.Reflection; using System.Reflection;
namespace HelloShop.IdentityService.Controllers; namespace HelloShop.IdentityService.Controllers;

View File

@ -1,7 +1,8 @@
using HelloShop.IdentityService.Entities; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.IdentityService.Entities;
using HelloShop.IdentityService.EntityFrameworks; using HelloShop.IdentityService.EntityFrameworks;
using HelloShop.ServiceDefaults.Authorization;
using HelloShop.ServiceDefaults.Constants;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -9,12 +10,13 @@ using Microsoft.EntityFrameworkCore;
[Route("api/[controller]")] [Route("api/[controller]")]
[ApiController] [ApiController]
[Authorize] [Authorize]
public class PermissionsController(IPermissionChecker permissionChecker) : ControllerBase public class PermissionsController(IdentityServiceDbContext dbContext) : ControllerBase
{ {
[HttpHead] [HttpHead]
public async Task<IActionResult> CheckPermission(string permissionName, string? resourceType = null, string? resourceId = null) public async Task<IActionResult> CheckPermission(int roleId, string permissionName, string? resourceType = null, string? resourceId = null)
{ {
if(await permissionChecker.IsGrantedAsync(permissionName, resourceType, resourceId))
if (await dbContext.Set<PermissionGranted>().AnyAsync(x => x.RoleId == roleId && x.PermissionName == permissionName && x.ResourceType == resourceType && x.ResourceId == resourceId))
{ {
return Ok(); return Ok();
} }

View File

@ -1,14 +1,17 @@
using AutoMapper; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using AutoMapper;
using FluentValidation; using FluentValidation;
using HelloShop.IdentityService.Entities; using HelloShop.IdentityService.Entities;
using HelloShop.IdentityService.EntityFrameworks; using HelloShop.IdentityService.EntityFrameworks;
using HelloShop.IdentityService.Models.Users; using HelloShop.IdentityService.Models.Users;
using HelloShop.ServiceDefaults.Authorization; using HelloShop.ServiceDefaults.Authorization;
using HelloShop.ServiceDefaults.Extensions;
using HelloShop.ServiceDefaults.Models.Paging; using HelloShop.ServiceDefaults.Models.Paging;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using HelloShop.ServiceDefaults.Extensions;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860 // For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
@ -28,7 +31,7 @@ namespace HelloShop.IdentityService.Controllers
{ {
users = users.Where(e => e.UserName != null && e.UserName.Contains(model.Keyword)); users = users.Where(e => e.UserName != null && e.UserName.Contains(model.Keyword));
} }
users = users.WhereIf(model.PhoneNumber is not null, e => e.PhoneNumber == model.PhoneNumber); users = users.WhereIf(model.PhoneNumber is not null, e => e.PhoneNumber == model.PhoneNumber);
IQueryable<User> pagedUsers = users.SortAndPageBy(model); IQueryable<User> pagedUsers = users.SortAndPageBy(model);

View File

@ -1,3 +1,6 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace HelloShop.IdentityService.Controllers; namespace HelloShop.IdentityService.Controllers;

View File

@ -1,5 +1,7 @@
using HelloShop.IdentityService.Entities; // Copyright (c) HelloShop Corporation. All rights reserved.
using HelloShop.IdentityService.EntityFrameworks; // See the license file in the project root for more information.
using HelloShop.IdentityService.Entities;
using HelloShop.ServiceDefaults.Infrastructure; using HelloShop.ServiceDefaults.Infrastructure;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService.Entities; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService.Entities;
public class PermissionGranted public class PermissionGranted
{ {

View File

@ -5,8 +5,8 @@ using Microsoft.AspNetCore.Identity;
namespace HelloShop.IdentityService.Entities namespace HelloShop.IdentityService.Entities
{ {
public class Role: IdentityRole<int> public class Role : IdentityRole<int>
{ {
public DateTimeOffset CreationTime { get; set; }=TimeProvider.System.GetUtcNow(); public DateTimeOffset CreationTime { get; set; } = TimeProvider.System.GetUtcNow();
} }
} }

View File

@ -2,7 +2,6 @@
// See the license file in the project root for more information. // See the license file in the project root for more information.
using HelloShop.ServiceDefaults.Authorization; using HelloShop.ServiceDefaults.Authorization;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
namespace HelloShop.IdentityService.Entities namespace HelloShop.IdentityService.Entities

View File

@ -1,4 +1,7 @@
using HelloShop.IdentityService.Entities; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.IdentityService.Entities;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations; namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations;

View File

@ -2,8 +2,8 @@
// See the license file in the project root for more information. // See the license file in the project root for more information.
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations
{ {

View File

@ -2,8 +2,8 @@
// See the license file in the project root for more information. // See the license file in the project root for more information.
using HelloShop.IdentityService.Entities; using HelloShop.IdentityService.Entities;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations
{ {

View File

@ -2,8 +2,8 @@
// See the license file in the project root for more information. // See the license file in the project root for more information.
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations
{ {

View File

@ -1,4 +1,7 @@
using HelloShop.IdentityService.Entities; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.IdentityService.Entities;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;

View File

@ -2,8 +2,8 @@
// See the license file in the project root for more information. // See the license file in the project root for more information.
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations
{ {

View File

@ -2,8 +2,8 @@
// See the license file in the project root for more information. // See the license file in the project root for more information.
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations namespace HelloShop.IdentityService.EntityFrameworks.EntityConfigurations
{ {

View File

@ -1,4 +1,7 @@
using HelloShop.IdentityService.Entities; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.IdentityService.Entities;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System.Reflection; using System.Reflection;

View File

@ -1,4 +1,6 @@
using System; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;

View File

@ -1,23 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.0-preview.3.24172.13" /> <ProjectReference Include="..\HelloShop.ServiceDefaults\HelloShop.ServiceDefaults.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="9.0.0-preview.3.24172.13" /> </ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0-preview.3.24172.4"> <ItemGroup>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
<PrivateAssets>all</PrivateAssets> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.6" />
</PackageReference> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.6">
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0-preview.3" /> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</ItemGroup> <PrivateAssets>all</PrivateAssets>
<ItemGroup> </PackageReference>
<ProjectReference Include="..\HelloShop.ServiceDefaults\HelloShop.ServiceDefaults.csproj" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.4" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Resources\Models\" />
<Folder Include="Resources\Models\Users\" />
</ItemGroup>
</Project> </Project>

View File

@ -1,16 +1,19 @@
using System.Text.Json.Serialization; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using System.Text.Json.Serialization;
namespace HelloShop.IdentityService; namespace HelloShop.IdentityService;
public class AccountLoginRequest public class AccountLoginRequest
{ {
public required string UserName { get; init; } public required string UserName { get; init; }
public required string Password { get; init; } public required string Password { get; init; }
[JsonIgnore] [JsonIgnore]
public string? TwoFactorCode { get; init; } public string? TwoFactorCode { get; init; }
[JsonIgnore] [JsonIgnore]
public string? TwoFactorRecoveryCode { get; init; } public string? TwoFactorRecoveryCode { get; init; }
} }

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService;
public class AccountRefreshRequest public class AccountRefreshRequest
{ {

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService;
public class AccountRegisterRequest public class AccountRegisterRequest
{ {

View File

@ -1,5 +1,5 @@
using System.ComponentModel; // Copyright (c) HelloShop Corporation. All rights reserved.
using System.ComponentModel.DataAnnotations; // See the license file in the project root for more information.
namespace HelloShop.IdentityService.Models.Users; namespace HelloShop.IdentityService.Models.Users;

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService.Models.Users; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService.Models.Users;
public class UserDetailsResponse public class UserDetailsResponse
{ {

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService;
public class UserListItem public class UserListItem
{ {

View File

@ -1,4 +1,7 @@
using HelloShop.ServiceDefaults.Models.Paging; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ServiceDefaults.Models.Paging;
namespace HelloShop.IdentityService.Models.Users; namespace HelloShop.IdentityService.Models.Users;

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService.Models.Users; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService.Models.Users;
public class UserUpdateRequest public class UserUpdateRequest
{ {

View File

@ -1,4 +1,7 @@
using HelloShop.ServiceDefaults.Permissions; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ServiceDefaults.Permissions;
namespace HelloShop.IdentityService; namespace HelloShop.IdentityService;

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService;
public static class IdentityPermissions public static class IdentityPermissions
{ {

View File

@ -1,7 +1,9 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.IdentityService; using HelloShop.IdentityService;
using HelloShop.IdentityService.Authorization; using HelloShop.IdentityService.Authorization;
using HelloShop.IdentityService.Constants; using HelloShop.IdentityService.Constants;
using HelloShop.IdentityService.DataSeeding;
using HelloShop.IdentityService.Entities; using HelloShop.IdentityService.Entities;
using HelloShop.IdentityService.EntityFrameworks; using HelloShop.IdentityService.EntityFrameworks;
using HelloShop.ServiceDefaults.Authorization; using HelloShop.ServiceDefaults.Authorization;
@ -64,8 +66,6 @@ var app = builder.Build();
app.MapDefaultEndpoints(); app.MapDefaultEndpoints();
app.UseHttpsRedirection();
app.UseAuthorization(); app.UseAuthorization();
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

View File

@ -1,20 +1,12 @@
{ {
"$schema": "http://json.schemastore.org/launchsettings.json", "$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:20874",
"sslPort": 44391
}
},
"profiles": { "profiles": {
"http": { "http": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "swagger", "launchUrl": "swagger",
"applicationUrl": "http://localhost:5119", "applicationUrl": "http://localhost:8002",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
@ -24,18 +16,10 @@
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "swagger", "launchUrl": "swagger",
"applicationUrl": "https://localhost:7266;http://localhost:5119", "applicationUrl": "https://localhost:8102;http://localhost:8002",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
} }
} }
} }

View File

@ -1,4 +1,7 @@
using FluentValidation; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using FluentValidation;
using HelloShop.IdentityService.Entities; using HelloShop.IdentityService.Entities;
using HelloShop.IdentityService.EntityFrameworks; using HelloShop.IdentityService.EntityFrameworks;
using HelloShop.IdentityService.Models.Users; using HelloShop.IdentityService.Models.Users;
@ -9,7 +12,7 @@ namespace HelloShop.IdentityService.Validations.Users;
public class UserCreateRequestValidator : AbstractValidator<UserCreateRequest> public class UserCreateRequestValidator : AbstractValidator<UserCreateRequest>
{ {
public UserCreateRequestValidator(IdentityServiceDbContext dbContext,IStringLocalizer<UserCreateRequest> localizer ) public UserCreateRequestValidator(IdentityServiceDbContext dbContext, IStringLocalizer<UserCreateRequest> localizer)
{ {
RuleFor(m => m.UserName).NotNull().NotEmpty().Length(8, 16).Matches("^[a-zA-Z]+$"); RuleFor(m => m.UserName).NotNull().NotEmpty().Length(8, 16).Matches("^[a-zA-Z]+$");

View File

@ -1,4 +1,7 @@
using FluentValidation; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using FluentValidation;
using HelloShop.IdentityService.Entities; using HelloShop.IdentityService.Entities;
using HelloShop.IdentityService.EntityFrameworks; using HelloShop.IdentityService.EntityFrameworks;
using HelloShop.IdentityService.Models.Users; using HelloShop.IdentityService.Models.Users;

View File

@ -1,3 +1,6 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService; namespace HelloShop.IdentityService;
public class WeatherForecast public class WeatherForecast

View File

@ -1,4 +1,7 @@
namespace HelloShop.IdentityService; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.IdentityService;
public class Welcome public class Welcome
{ {

View File

@ -1,3 +1,6 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace HelloShop.OrderingService.Controllers; namespace HelloShop.OrderingService.Controllers;

View File

@ -1,12 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\HelloShop.ServiceDefaults\HelloShop.ServiceDefaults.csproj" /> <ProjectReference Include="..\HelloShop.ServiceDefaults\HelloShop.ServiceDefaults.csproj" />
</ItemGroup> </ItemGroup>

View File

@ -1,3 +1,6 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ServiceDefaults.Extensions; using HelloShop.ServiceDefaults.Extensions;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -13,8 +16,6 @@ var app = builder.Build();
app.MapDefaultEndpoints(); app.MapDefaultEndpoints();
app.UseHttpsRedirection();
app.UseAuthorization(); app.UseAuthorization();
app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); app.UseCors(options => options.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());

View File

@ -1,20 +1,12 @@
{ {
"$schema": "http://json.schemastore.org/launchsettings.json", "$schema": "https://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:39547",
"sslPort": 44369
}
},
"profiles": { "profiles": {
"http": { "http": {
"commandName": "Project", "commandName": "Project",
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "swagger", "launchUrl": "swagger",
"applicationUrl": "http://localhost:5015", "applicationUrl": "http://localhost:8005",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
@ -24,18 +16,10 @@
"dotnetRunMessages": true, "dotnetRunMessages": true,
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "swagger", "launchUrl": "swagger",
"applicationUrl": "https://localhost:7250;http://localhost:5015", "applicationUrl": "https://localhost:8105;http://localhost:8005",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
} }
} }
} }

View File

@ -1,3 +1,6 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.OrderingService; namespace HelloShop.OrderingService;
public class WeatherForecast public class WeatherForecast

View File

@ -1,4 +1,7 @@
using AutoMapper; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using AutoMapper;
using HelloShop.ProductService.Entities.Products; using HelloShop.ProductService.Entities.Products;
using HelloShop.ProductService.Models.Products; using HelloShop.ProductService.Models.Products;

View File

@ -1,4 +1,7 @@
namespace HelloShop.ProductService.Constants; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.ProductService.Constants;
public static class DbConstants public static class DbConstants
{ {

View File

@ -1,13 +1,16 @@
using AutoMapper; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using AutoMapper;
using HelloShop.ProductService.Entities.Products; using HelloShop.ProductService.Entities.Products;
using HelloShop.ProductService.EntityFrameworks; using HelloShop.ProductService.EntityFrameworks;
using HelloShop.ProductService.Models.Products; using HelloShop.ProductService.Models.Products;
using HelloShop.ProductService.PermissionProviders;
using HelloShop.ServiceDefaults.Extensions;
using HelloShop.ServiceDefaults.Models.Paging; using HelloShop.ServiceDefaults.Models.Paging;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using HelloShop.ServiceDefaults.Extensions;
using Microsoft.AspNetCore.Authorization;
using HelloShop.ProductService.PermissionProviders;
namespace HelloShop.ProductService; namespace HelloShop.ProductService;
[Route("api/[controller]")] [Route("api/[controller]")]

View File

@ -0,0 +1,93 @@
// Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using AutoMapper;
using HelloShop.ProductService.Entities.Products;
using HelloShop.ProductService.Models.Products;
using HelloShop.ProductService.PermissionProviders;
using HelloShop.ProductService.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace HelloShop.ProductService.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class MockProductsController(IProductService productService, IMapper mapper) : ControllerBase
{
[HttpGet]
[Authorize(CatalogPermissions.Products.Default)]
public async Task<ActionResult<IEnumerable<ProductListItem>>> GetProducts()
{
List<Product> products = await productService.GetAllAsync();
return mapper.Map<List<ProductListItem>>(products);
}
[HttpGet("{id}")]
[Authorize(CatalogPermissions.Products.Details)]
public async Task<ActionResult<ProductDetailsResponse>> GetProduct(int id)
{
Product? entity = await productService.FindAsync(id);
if (entity is null)
{
return NotFound();
}
return mapper.Map<ProductDetailsResponse>(entity);
}
[HttpPost]
[Authorize(CatalogPermissions.Products.Create)]
public async Task<ActionResult<ProductDetailsResponse>> PostProduct(ProductCreateRequest model)
{
Product entity = mapper.Map<Product>(model);
await productService.CreateAsync(entity);
ProductDetailsResponse result = mapper.Map<ProductDetailsResponse>(entity);
return CreatedAtAction(nameof(GetProduct), new { id = entity.Id }, result);
}
[HttpPut("{id}")]
[Authorize(CatalogPermissions.Products.Update)]
public async Task<IActionResult> PutProduct(int id, ProductUpdateRequest model)
{
if (id != model.Id)
{
return BadRequest();
}
Product? entity = await productService.FindAsync(id);
if (entity is null)
{
return NotFound();
}
mapper.Map(model, entity);
await productService.UpdateAsyc(entity);
return NoContent();
}
[HttpDelete("{id}")]
[Authorize(CatalogPermissions.Products.Delete)]
public async Task<IActionResult> DeleteProduct(int id)
{
Product? entity = await productService.FindAsync(id);
if (entity is null)
{
return NotFound();
}
await productService.DeleteAsync(entity);
return NoContent();
}
}
}

View File

@ -1,118 +1,121 @@
using HelloShop.ProductService.Entities.Products; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using AutoMapper;
using HelloShop.ProductService.Entities.Products;
using HelloShop.ProductService.EntityFrameworks; using HelloShop.ProductService.EntityFrameworks;
using HelloShop.ProductService.Models.Products; using HelloShop.ProductService.Models.Products;
using HelloShop.ServiceDefaults.Models.Paging;
using Microsoft.AspNetCore.Mvc;
using HelloShop.ServiceDefaults.Extensions;
using AutoMapper;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;
using HelloShop.ProductService.PermissionProviders; using HelloShop.ProductService.PermissionProviders;
using HelloShop.ServiceDefaults.Extensions;
using HelloShop.ServiceDefaults.Models.Paging;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace HelloShop.ProductService; namespace HelloShop.ProductService;
[Route("api/[controller]")] [Route("api/[controller]")]
[ApiController] [ApiController]
public class ProductsController(ProductServiceDbContext dbContext, IMapper mapper) : ControllerBase public class ProductsController(ProductServiceDbContext dbContext, IMapper mapper) : ControllerBase
{ {
[HttpGet] [HttpGet]
[Authorize(CatalogPermissions.Products.Default)] [Authorize(CatalogPermissions.Products.Default)]
public async Task<ActionResult<PagedResponse<ProductListItem>>> GetProducts([FromQuery] KeywordSearchRequest model) public async Task<ActionResult<PagedResponse<ProductListItem>>> GetProducts([FromQuery] KeywordSearchRequest model)
{ {
IQueryable<Product> query = dbContext.Set<Product>().Include(x => x.Brand).AsNoTracking(); IQueryable<Product> query = dbContext.Set<Product>().Include(x => x.Brand).AsNoTracking();
query = query.WhereIf(model.Keyword is not null, x => model.Keyword != null && x.Name.Contains(model.Keyword)); query = query.WhereIf(model.Keyword is not null, x => model.Keyword != null && x.Name.Contains(model.Keyword));
var pagedProducts = query.SortAndPageBy(model); var pagedProducts = query.SortAndPageBy(model);
return new PagedResponse<ProductListItem>(mapper.Map<List<ProductListItem>>(await pagedProducts.ToListAsync()), await query.CountAsync()); return new PagedResponse<ProductListItem>(mapper.Map<List<ProductListItem>>(await pagedProducts.ToListAsync()), await query.CountAsync());
} }
[HttpGet("{id}")] [HttpGet("{id}")]
[Authorize(CatalogPermissions.Products.Details)] [Authorize(CatalogPermissions.Products.Details)]
public async Task<ActionResult<ProductDetailsResponse>> GetProduct(int id) public async Task<ActionResult<ProductDetailsResponse>> GetProduct(int id)
{ {
Product? entity = await dbContext.Set<Product>().FindAsync(id); Product? entity = await dbContext.Set<Product>().FindAsync(id);
if (entity is null) if (entity is null)
{ {
return NotFound(); return NotFound();
} }
await dbContext.Entry(entity).Reference(e => e.Brand).LoadAsync(); await dbContext.Entry(entity).Reference(e => e.Brand).LoadAsync();
return mapper.Map<ProductDetailsResponse>(entity); return mapper.Map<ProductDetailsResponse>(entity);
} }
[HttpPost] [HttpPost]
[Authorize(CatalogPermissions.Products.Create)] [Authorize(CatalogPermissions.Products.Create)]
public async Task<ActionResult<ProductDetailsResponse>> PostProduct(ProductCreateRequest model) public async Task<ActionResult<ProductDetailsResponse>> PostProduct(ProductCreateRequest model)
{ {
Product entity = mapper.Map<Product>(model); Product entity = mapper.Map<Product>(model);
await dbContext.AddAsync(entity); await dbContext.AddAsync(entity);
await dbContext.SaveChangesAsync(); await dbContext.SaveChangesAsync();
ProductDetailsResponse result = mapper.Map<ProductDetailsResponse>(entity); ProductDetailsResponse result = mapper.Map<ProductDetailsResponse>(entity);
return CreatedAtAction(nameof(GetProduct), new { id = entity.Id }, result); return CreatedAtAction(nameof(GetProduct), new { id = entity.Id }, result);
} }
[HttpPut("{id}")] [HttpPut("{id}")]
[Authorize(CatalogPermissions.Products.Update)] [Authorize(CatalogPermissions.Products.Update)]
public async Task<IActionResult> PutProduct(int id, ProductUpdateRequest model) public async Task<IActionResult> PutProduct(int id, ProductUpdateRequest model)
{ {
if (id != model.Id) if (id != model.Id)
{ {
return BadRequest(); return BadRequest();
} }
Product entity = mapper.Map<Product>(model); Product entity = mapper.Map<Product>(model);
dbContext.Entry(entity).State = EntityState.Modified; dbContext.Entry(entity).State = EntityState.Modified;
try try
{ {
await dbContext.SaveChangesAsync(); await dbContext.SaveChangesAsync();
} }
catch (DbUpdateConcurrencyException) catch (DbUpdateConcurrencyException)
{ {
if (!dbContext.Set<Product>().Any(e => e.Id == id)) if (!dbContext.Set<Product>().Any(e => e.Id == id))
{ {
return NotFound(); return NotFound();
} }
else else
{ {
throw; throw;
} }
} }
return NoContent(); return NoContent();
} }
[HttpDelete("{id}")] [HttpDelete("{id}")]
[Authorize(CatalogPermissions.Products.Delete)] [Authorize(CatalogPermissions.Products.Delete)]
public async Task<IActionResult> DeleteProduct(int id) public async Task<IActionResult> DeleteProduct(int id)
{ {
Product? entity = await dbContext.Set<Product>().FindAsync(id); Product? entity = await dbContext.Set<Product>().FindAsync(id);
if (entity is null) if (entity is null)
{ {
return NotFound(); return NotFound();
} }
dbContext.Remove(entity); dbContext.Remove(entity);
await dbContext.SaveChangesAsync(); await dbContext.SaveChangesAsync();
return NoContent(); return NoContent();
} }
[HttpDelete] [HttpDelete]
[Authorize(CatalogPermissions.Products.Delete)] [Authorize(CatalogPermissions.Products.Delete)]
public async Task<IActionResult> DeleteProducts([FromQuery] IEnumerable<int> ids) public async Task<IActionResult> DeleteProducts([FromQuery] IEnumerable<int> ids)
{ {
await dbContext.Set<Product>().Where(e => ids.Contains(e.Id)).ExecuteDeleteAsync(); await dbContext.Set<Product>().Where(e => ids.Contains(e.Id)).ExecuteDeleteAsync();
return NoContent(); return NoContent();
} }
} }

View File

@ -1,4 +1,7 @@
using HelloShop.ProductService.Entities.Products; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ProductService.Entities.Products;
using HelloShop.ProductService.EntityFrameworks; using HelloShop.ProductService.EntityFrameworks;
using HelloShop.ServiceDefaults.Infrastructure; using HelloShop.ServiceDefaults.Infrastructure;
@ -84,7 +87,7 @@ namespace HelloShop.ProductService.DataSeeding
foreach (var product in productList) foreach (var product in productList)
{ {
product.Brand = brand; product.Brand = brand;
await dbContext.AddAsync(product); await dbContext.AddAsync(product);
} }
} }

View File

@ -1,4 +1,7 @@
namespace HelloShop.ProductService.Entities.Products // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.ProductService.Entities.Products
{ {
public class Brand public class Brand
{ {

View File

@ -1,4 +1,7 @@
namespace HelloShop.ProductService.Entities.Products // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
namespace HelloShop.ProductService.Entities.Products
{ {
public class Product public class Product
{ {

View File

@ -1,14 +1,17 @@
using HelloShop.ProductService.Entities.Products; // Copyright (c) HelloShop Corporation. All rights reserved.
// See the license file in the project root for more information.
using HelloShop.ProductService.Entities.Products;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace HelloShop.ProductService.EntityFrameworks.EntityConfigurations.Products; namespace HelloShop.ProductService.EntityFrameworks.EntityConfigurations.Products;
public class BrandEntityTypeConfiguration : IEntityTypeConfiguration<Brand> public class BrandEntityTypeConfiguration : IEntityTypeConfiguration<Brand>
{
public void Configure(EntityTypeBuilder<Brand> builder)
{ {
public void Configure(EntityTypeBuilder<Brand> builder) builder.ToTable("Brands");
{ builder.Property(x => x.Name).HasMaxLength(32);
builder.ToTable("Brands"); }
builder.Property(x => x.Name).HasMaxLength(32); }
}
}

Some files were not shown because too many files have changed in this diff Show More