Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
{
"UpstreamPathTemplate": "/api/review/{everything}",
"UpstreamHttpMethod": ["GET"],
"DownstreamPathTemplate": "/api/review/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "review_service",
"Port": 8080
}
]
},
{
"UpstreamPathTemplate": "/api/review/{everything}",
"UpstreamHttpMethod": ["POST", "PUT", "DELETE"],
"DownstreamPathTemplate": "/api/review/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "review_service",
"Port": 8080
}
]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,17 @@
],
"UpstreamPathTemplate": "/swagger/notification",
"UpstreamHttpMethod": ["GET"]
},
{
"DownstreamPathTemplate": "/swagger/v1/swagger.json",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "review_service",
"Port": 8080
}
],
"UpstreamPathTemplate": "/swagger/review",
"UpstreamHttpMethod": ["GET"]
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public static void ConfigureSwagger(this IServiceCollection services)
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Inventory Service", Version = "v1" });
c.SwaggerDoc("v2", new OpenApiInfo { Title = "User Service", Version = "v1" });
c.SwaggerDoc("v3", new OpenApiInfo { Title = "Payment Service", Version = "v1" });
c.SwaggerDoc("v4", new OpenApiInfo { Title = "Notification Service", Version = "v1" });
c.SwaggerDoc("v5", new OpenApiInfo { Title = "Review Service", Version = "v1" });
});
}

Expand All @@ -24,6 +26,7 @@ public static void UseSwaggerConfig(this WebApplication app)
c.SwaggerEndpoint("http://localhost:5001/swagger/user", "User Service V1");
c.SwaggerEndpoint("http://localhost:5001/swagger/payment", "Payment Service V1");
c.SwaggerEndpoint("http://localhost:5001/swagger/notification", "Notification Service V1");
c.SwaggerEndpoint("http://localhost:5001/swagger/review", "Review Service V1");
c.RoutePrefix = string.Empty;
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
Env.Load("../../../.env");
var builder = WebApplication.CreateBuilder(args);
var apiGatewayUrl = builder.Configuration["ApiGatewayUrl"] ?? "http://localhost:5001";

builder.Services.AddCors(options =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Commons.Dto;

public class PaginatedResponseDto<T>(List<T> items, int totalItems, int page, int pageSize)
{
public List<T>? Items { get; set; } = items;
public int TotalCount { get; set; } = items.Count;
public int Page { get; set; } = page;
public int PageSize { get; set; } = pageSize;
public int TotalItems { get; set; } = totalItems;
public int TotalPages { get; set; } = (int)Math.Ceiling(totalItems / (double)pageSize);
}
29 changes: 29 additions & 0 deletions apps/merchant-api/ReviewService/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app

COPY ReviewService/src/ReviewService.Api/ReviewService.Api.csproj ReviewService/src/ReviewService.Api/
COPY ReviewService/src/ReviewService.Application/ReviewService.Application.csproj ReviewService/src/ReviewService.Application/
COPY ReviewService/src/ReviewService.Domain/ReviewService.Domain.csproj ReviewService/src/ReviewService.Domain/
COPY ReviewService/src/ReviewService.Infrastructure/ReviewService.Infrastructure.csproj ReviewService/src/ReviewService.Infrastructure/
COPY MerchantCommon/RabbitMqMessaging/RabbitMqMessaging.csproj MerchantCommon/RabbitMqMessaging/
COPY NotificationService/src/NotificationService.Domain/NotificationService.Domain.csproj NotificationService/src/NotificationService.Domain/
COPY MerchantCommon/Commons/Commons.csproj MerchantCommon/Commons/

WORKDIR /app/ReviewService/src/ReviewService.Api
RUN dotnet restore

COPY ReviewService/src/ReviewService.Api/. .
COPY ReviewService/src/ReviewService.Application/. ../ReviewService.Application/
COPY ReviewService/src/ReviewService.Domain/. ../ReviewService.Domain/
COPY ReviewService/src/ReviewService.Infrastructure/. ../ReviewService.Infrastructure/
COPY NotificationService/src/NotificationService.Domain/. /app/NotificationService/src/NotificationService.Domain/
COPY MerchantCommon/RabbitMqMessaging/. /app/MerchantCommon/RabbitMqMessaging/
COPY MerchantCommon/Commons/. /app/MerchantCommon/Commons/

RUN dotnet publish -c Release -o /app/out

FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app/out .
EXPOSE 8080
ENTRYPOINT ["dotnet", "ReviewService.Api.dll"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using MongoDB.Driver;
using ReviewService.Concretes;
using ReviewService.Infrastructure.Context.Concretes;
using ReviewService.Infrastructure.Context.Interfaces;

namespace ReviewService.Api.Configuration;

public static class ConfigDb
{
public static IServiceCollection ConfigDbSet(this IServiceCollection services, string connectionString)
{
var client = new MongoClient(connectionString);
var db = client.GetDatabase("reviews_db");

services.AddScoped<IMongoDatabase>(_ => db);
services.ConfigContext();
return services;
}

public static IServiceCollection ConfigContext(this IServiceCollection services)
{
services.AddScoped<IContext<ProductReview>, ProductReviewContext>();
return services;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using ReviewService.Concretes;
using ReviewService.Infrastructure.Repositories.Concretes;
using ReviewService.Infrastructure.Repositories.Interfaces;

namespace ReviewService.Api.Configuration;

public static class ConfigRepositories
{
public static IServiceCollection AddRepositories(this IServiceCollection services)
{
return services.AddScoped<IRepository<ProductReview>, ProductReviewRepository>();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using Commons.ResponseHandler.Responses.Concretes;

using MediatR;
using Microsoft.AspNetCore.Mvc;
using ReviewService.Application.CommandsQueries.Commons;
using ReviewService.Application.CommandsQueries.ProductReview.Commands.Requests;
using ReviewService.Application.CommandsQueries.ProductReview.Queries.Requests;
using ReviewService.Application.Dtos.ProductReview;
using ReviewService.Application.Dtos.Review;
using ReviewService.Concretes;

namespace ReviewService.Api.Controllers;

[ApiController]
[Route("api/review/[controller]")]
public class ProductReviewController(IMediator mediator) : ControllerBase
{
[HttpPost]
public async Task<ActionResult> Create(CreateProductReviewDto productReview)
{
var result = await mediator.Send(new CreateProductReview(productReview));
if (result is ErrorResponse errorResponse)
return StatusCode(errorResponse.StatusCode, errorResponse);
var successResponse = (SuccessResponse<ProductReview>)result;
return StatusCode(successResponse.StatusCode, successResponse);
}

[HttpPost("{productId}")]
public async Task<ActionResult> AddReview(Guid productId, CreateReviewDto review)
{
var result = await mediator.Send(new AddReview(productId, review));
if (result is ErrorResponse errorResponse)
return StatusCode(errorResponse.StatusCode, errorResponse);
var successResponse = (SuccessResponse<Review>)result;
return StatusCode(successResponse.StatusCode, successResponse);
}

[HttpGet("{id}")]
public async Task<ActionResult> GetProductReview(Guid id, Guid? clientId, int page, int pageSize)
{
var result = await mediator
.Send(new GetProductReviewById(id, clientId, new PaginationRequest(page, pageSize)));
if (result is ErrorResponse errorResponse)
return StatusCode(errorResponse.StatusCode, errorResponse);
var successResponse = (SuccessResponse<ProductReviewDto>)result;
return StatusCode(successResponse.StatusCode, successResponse);
}

[HttpPatch("{productId}")]
public async Task<ActionResult> UpdateReview(Guid productId, Guid clientId, UpdateReviewDto updateReviewDto)
{
var result = await mediator.Send(new UpdateReview(productId, clientId, updateReviewDto));
if (result is ErrorResponse errorResponse)
return StatusCode(errorResponse.StatusCode, errorResponse);
var successResponse = (SuccessResponse<Review>)result;
return StatusCode(successResponse.StatusCode, successResponse);
}

[HttpDelete("{productId}")]
public async Task<ActionResult> DeleteReview(Guid productId, Guid clientId)
{
var result = await mediator.Send(new DeleteReview(productId, clientId));
if (result is ErrorResponse errorResponse)
return StatusCode(errorResponse.StatusCode, errorResponse);
var successResponse = (SuccessResponse<Review>)result;
return StatusCode(successResponse.StatusCode, successResponse);
}
}
58 changes: 58 additions & 0 deletions apps/merchant-api/ReviewService/src/ReviewService.Api/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using Commons.ResponseHandler.Handler.Concretes;
using Commons.ResponseHandler.Handler.Interfaces;
using DotNetEnv;
using FluentValidation;
using ReviewService.Api;
using ReviewService.Api.Configuration;
using ReviewService.Application.Profiles;
using ReviewService.Application.ValidationSettings;

Env.Load("../../../.env");
var builder = WebApplication.CreateBuilder(args);
builder.Configuration.AddEnvironmentVariables();

builder.Configuration.AddJsonFile("validationSettings.json", optional: false, reloadOnChange: true);
builder.Services.Configure<ValidationSettings>(builder.Configuration);

var apiGateway = builder.Configuration["ApiGatewayUrl"] ?? "http://localhost:5001";
builder.Services.AddCors(options =>
{
options.AddPolicy("AllowedLocalhost",
policyBuilder => policyBuilder
.WithOrigins(apiGateway)
.AllowAnyHeader()
.AllowAnyMethod());
});

var connectionString = builder.Configuration["MONGODB_URI"];
if (connectionString == null)
{
Console.WriteLine("You must set your 'MONGODB_URI' environment variable. To learn how to set it, see https://www.mongodb.com/docs/drivers/csharp/current/quick-start/#set-your-connection-string");
Environment.Exit(0);
}

builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.ConfigureSwagger();

builder.Services.AddRepositories();
builder.Services.ConfigDbSet(connectionString);
builder.Services.AddValidatorsFromAssembly(typeof(ReviewServiceProfile).Assembly);
builder.Services.AddAutoMapper(typeof(ReviewServiceProfile));
builder.Services.AddMediatR(cfg =>
cfg.RegisterServicesFromAssemblies(typeof(ReviewServiceProfile).Assembly));
builder.Services.AddScoped<IResponseHandlingHelper, ResponseHandlingHelper>();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.MapControllers();
app.UseCors("AllowApiGateway");
app.UseAuthentication();
app.UseAuthorization();
app.Run();
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:12039",
"sslPort": 44349
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5500",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7269;http://localhost:5500",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>ReviewService.Api</RootNamespace>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DotNetEnv" Version="3.1.1" />
<PackageReference Include="FluentValidation" Version="11.11.0" />
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" Version="11.11.0" />
<PackageReference Include="MediatR" Version="12.4.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.4"/>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\MerchantCommon\Commons\Commons.csproj" />
<ProjectReference Include="..\..\..\MerchantCommon\Commons\Commons.csproj" />
<ProjectReference Include="..\ReviewService.Application\ReviewService.Application.csproj" />
<ProjectReference Include="..\ReviewService.Infrastructure\ReviewService.Infrastructure.csproj" />
</ItemGroup>
</Project>
Loading