feat: Implement file management and authorization features
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 3m9s
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 3m9s
- Add RequiresPermissionAttribute for gRPC method access control. - Create IFileManagementService interface for file upload and management. - Implement AddProductImageCommand and handler for adding product images. - Implement CreateNewProductsCommand and handler for creating new products with image uploads. - Implement DeleteProductsCommand and handler for deleting products and their associations. - Implement RemoveProductImageCommand and handler for removing product images from galleries. - Implement UpdateProductsCommand and handler for updating product details and images. - Create GetProductGalleryQuery and handler for retrieving product galleries. - Implement PermissionService for role-based access control using JWT claims. - Implement FileManagementService for handling file uploads and image optimization. - Define gRPC service and messages for file management in fms.proto. - Add FluentValidation for request validation in various commands. - Create PermissionInterceptor for enforcing permissions on gRPC methods.
This commit is contained in:
@@ -1,16 +1,22 @@
|
||||
using CMSMicroservice.Protobuf.Protos.City;
|
||||
using CMSMicroservice.WebApi.Common.Services;
|
||||
using CMSMicroservice.Application.CityCQ.Queries.GetAllCitiesByFilter;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using System.Linq;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Services;
|
||||
|
||||
public class CityService : CityContract.CityContractBase
|
||||
{
|
||||
private readonly IDispatchRequestToCQRS _dispatchRequestToCQRS;
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public CityService(IDispatchRequestToCQRS dispatchRequestToCQRS)
|
||||
public CityService(IDispatchRequestToCQRS dispatchRequestToCQRS, IApplicationDbContext context)
|
||||
{
|
||||
_dispatchRequestToCQRS = dispatchRequestToCQRS;
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public override async Task<GetAllCitiesByFilterResponse> GetAllCitiesByFilter(
|
||||
@@ -28,18 +34,50 @@ public class CityService : CityContract.CityContractBase
|
||||
public override async Task<GetCitiesForCustomerResponse> GetCitiesForCustomer(
|
||||
GetCitiesForCustomerRequest request, ServerCallContext context)
|
||||
{
|
||||
// TODO: Implement using existing CMS City Application layer
|
||||
// For now, return empty response
|
||||
var pageNumber = request.PageNumber > 0 ? request.PageNumber : 1;
|
||||
var pageSize = request.PageSize > 0 ? request.PageSize : 50;
|
||||
|
||||
var query = _context.Cities
|
||||
.Include(c => c.State)
|
||||
.Where(c => !c.IsDeleted);
|
||||
|
||||
if (request.StateId != null)
|
||||
query = query.Where(c => c.StateId == request.StateId.Value);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(request.SearchTerm))
|
||||
query = query.Where(c => c.Name.Contains(request.SearchTerm) || c.Native.Contains(request.SearchTerm));
|
||||
|
||||
var totalCount = await query.CountAsync(context.CancellationToken);
|
||||
|
||||
var cities = await query
|
||||
.OrderBy(c => c.Native)
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(c => new CityDto
|
||||
{
|
||||
Id = c.Id,
|
||||
ExternalId = c.ExternalId,
|
||||
Name = c.Name,
|
||||
Native = c.Native,
|
||||
Latitude = c.Latitude ?? string.Empty,
|
||||
Longitude = c.Longitude ?? string.Empty,
|
||||
StateId = c.StateId,
|
||||
StateName = c.State != null ? c.State.Name : string.Empty,
|
||||
StateNative = c.State != null ? c.State.Native : string.Empty
|
||||
})
|
||||
.ToListAsync(context.CancellationToken);
|
||||
|
||||
return new GetCitiesForCustomerResponse
|
||||
{
|
||||
Cities = { cities },
|
||||
MetaData = new CMSMicroservice.Protobuf.Protos.City.MetaData
|
||||
{
|
||||
CurrentPage = request.PageNumber,
|
||||
PageSize = request.PageSize,
|
||||
TotalCount = 0,
|
||||
TotalPage = 0,
|
||||
HasNext = false,
|
||||
HasPrevious = false
|
||||
CurrentPage = pageNumber,
|
||||
PageSize = pageSize,
|
||||
TotalCount = totalCount,
|
||||
TotalPage = (int)Math.Ceiling(totalCount / (double)pageSize),
|
||||
HasNext = pageNumber * pageSize < totalCount,
|
||||
HasPrevious = pageNumber > 1
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -47,34 +85,126 @@ public class CityService : CityContract.CityContractBase
|
||||
public override async Task<GetCityByIdForCustomerResponse> GetCityByIdForCustomer(
|
||||
GetCityByIdForCustomerRequest request, ServerCallContext context)
|
||||
{
|
||||
// TODO: Implement using existing CMS City Application layer
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "GetCityByIdForCustomer not implemented yet"));
|
||||
var city = await _context.Cities
|
||||
.Include(c => c.State)
|
||||
.Where(c => c.Id == request.Id && !c.IsDeleted)
|
||||
.Select(c => new CityDto
|
||||
{
|
||||
Id = c.Id,
|
||||
ExternalId = c.ExternalId,
|
||||
Name = c.Name,
|
||||
Native = c.Native,
|
||||
Latitude = c.Latitude ?? string.Empty,
|
||||
Longitude = c.Longitude ?? string.Empty,
|
||||
StateId = c.StateId,
|
||||
StateName = c.State != null ? c.State.Name : string.Empty,
|
||||
StateNative = c.State != null ? c.State.Native : string.Empty
|
||||
})
|
||||
.FirstOrDefaultAsync(context.CancellationToken);
|
||||
|
||||
if (city == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "شهر یافت نشد"));
|
||||
|
||||
return new GetCityByIdForCustomerResponse { City = city };
|
||||
}
|
||||
|
||||
public override async Task<GetCitiesByStateForCustomerResponse> GetCitiesByStateForCustomer(
|
||||
GetCitiesByStateForCustomerRequest request, ServerCallContext context)
|
||||
{
|
||||
// TODO: Implement using existing CMS City Application layer
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "GetCitiesByStateForCustomer not implemented yet"));
|
||||
var pageNumber = request.PageNumber > 0 ? request.PageNumber : 1;
|
||||
var pageSize = request.PageSize > 0 ? request.PageSize : 100;
|
||||
|
||||
var query = _context.Cities
|
||||
.Include(c => c.State)
|
||||
.Where(c => c.StateId == request.StateId && !c.IsDeleted);
|
||||
|
||||
var totalCount = await query.CountAsync(context.CancellationToken);
|
||||
|
||||
var cities = await query
|
||||
.OrderBy(c => c.Native)
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(c => new CityDto
|
||||
{
|
||||
Id = c.Id,
|
||||
ExternalId = c.ExternalId,
|
||||
Name = c.Name,
|
||||
Native = c.Native,
|
||||
Latitude = c.Latitude ?? string.Empty,
|
||||
Longitude = c.Longitude ?? string.Empty,
|
||||
StateId = c.StateId,
|
||||
StateName = c.State != null ? c.State.Name : string.Empty,
|
||||
StateNative = c.State != null ? c.State.Native : string.Empty
|
||||
})
|
||||
.ToListAsync(context.CancellationToken);
|
||||
|
||||
return new GetCitiesByStateForCustomerResponse
|
||||
{
|
||||
Cities = { cities },
|
||||
MetaData = new CMSMicroservice.Protobuf.Protos.City.MetaData
|
||||
{
|
||||
CurrentPage = pageNumber,
|
||||
PageSize = pageSize,
|
||||
TotalCount = totalCount,
|
||||
TotalPage = (int)Math.Ceiling(totalCount / (double)pageSize),
|
||||
HasNext = pageNumber * pageSize < totalCount,
|
||||
HasPrevious = pageNumber > 1
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Admin Methods placeholder for future expansion
|
||||
// Admin Methods
|
||||
public override async Task<CreateCityResponse> CreateCity(
|
||||
CreateCityRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "CreateCity not implemented yet"));
|
||||
var city = new Domain.Entities.Geography.City
|
||||
{
|
||||
ExternalId = request.ExternalId,
|
||||
Name = request.Name,
|
||||
Native = request.Native,
|
||||
Latitude = request.Latitude ?? string.Empty,
|
||||
Longitude = request.Longitude ?? string.Empty,
|
||||
StateId = request.StateId
|
||||
};
|
||||
|
||||
_context.Cities.Add(city);
|
||||
await _context.SaveChangesAsync(context.CancellationToken);
|
||||
|
||||
return new CreateCityResponse
|
||||
{
|
||||
Id = city.Id,
|
||||
Message = "شهر با موفقیت ایجاد شد"
|
||||
};
|
||||
}
|
||||
|
||||
public override async Task<Empty> UpdateCity(
|
||||
UpdateCityRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "UpdateCity not implemented yet"));
|
||||
var city = await _context.Cities.FindAsync(new object[] { request.Id }, context.CancellationToken);
|
||||
if (city == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "شهر یافت نشد"));
|
||||
|
||||
city.ExternalId = request.ExternalId;
|
||||
city.Name = request.Name;
|
||||
city.Native = request.Native;
|
||||
if (request.Latitude != null) city.Latitude = request.Latitude;
|
||||
if (request.Longitude != null) city.Longitude = request.Longitude;
|
||||
city.StateId = request.StateId;
|
||||
|
||||
await _context.SaveChangesAsync(context.CancellationToken);
|
||||
return new Empty();
|
||||
}
|
||||
|
||||
public override async Task<Empty> DeleteCity(
|
||||
DeleteCityRequest request, ServerCallContext context)
|
||||
{
|
||||
throw new RpcException(new Status(StatusCode.Unimplemented, "DeleteCity not implemented yet"));
|
||||
var city = await _context.Cities.FindAsync(new object[] { request.Id }, context.CancellationToken);
|
||||
if (city == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "شهر یافت نشد"));
|
||||
|
||||
city.IsDeleted = true;
|
||||
await _context.SaveChangesAsync(context.CancellationToken);
|
||||
return new Empty();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
Reference in New Issue
Block a user