Adding inventory microservice
This commit is contained in:
@@ -0,0 +1,248 @@
|
||||
using InventoryApi.Models;
|
||||
using InventoryApi.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace InventoryApi.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class InventoryController : ControllerBase
|
||||
{
|
||||
private readonly InventoryStore _inventory;
|
||||
|
||||
public InventoryController(InventoryStore inventory)
|
||||
{
|
||||
_inventory = inventory;
|
||||
}
|
||||
|
||||
[HttpGet("by-owner/{ownerType}/{ownerId}")]
|
||||
[Authorize(Roles = "USER,SUPER")]
|
||||
public async Task<IActionResult> GetByOwner(string ownerType, string ownerId)
|
||||
{
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
return Unauthorized();
|
||||
|
||||
var access = await _inventory.ResolveOwnerAsync(ownerType, ownerId, userId, User.IsInRole("SUPER"));
|
||||
if (!access.IsSupported)
|
||||
return BadRequest("Unsupported ownerType");
|
||||
if (!access.Exists)
|
||||
return NotFound();
|
||||
if (!access.IsAuthorized)
|
||||
return Forbid();
|
||||
|
||||
var items = await _inventory.GetByOwnerAsync(access.OwnerType, access.OwnerId);
|
||||
return Ok(new InventoryOwnerResponse
|
||||
{
|
||||
OwnerType = access.OwnerType,
|
||||
OwnerId = access.OwnerId,
|
||||
Items = items.Select(InventoryItemResponse.FromModel).ToList()
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost("by-owner/{ownerType}/{ownerId}/grant")]
|
||||
[Authorize(Roles = "USER,SUPER")]
|
||||
public async Task<IActionResult> Grant(string ownerType, string ownerId, [FromBody] GrantInventoryItemRequest req)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(req.ItemKey))
|
||||
return BadRequest("itemKey required");
|
||||
if (req.Quantity <= 0)
|
||||
return BadRequest("quantity must be greater than 0");
|
||||
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
return Unauthorized();
|
||||
|
||||
var access = await _inventory.ResolveOwnerAsync(ownerType, ownerId, userId, User.IsInRole("SUPER"));
|
||||
if (!access.IsSupported)
|
||||
return BadRequest("Unsupported ownerType");
|
||||
if (!access.Exists)
|
||||
return NotFound();
|
||||
if (!access.IsAuthorized)
|
||||
return Forbid();
|
||||
|
||||
var items = await _inventory.GrantAsync(access, req);
|
||||
return Ok(new InventoryOwnerResponse
|
||||
{
|
||||
OwnerType = access.OwnerType,
|
||||
OwnerId = access.OwnerId,
|
||||
Items = items.Select(InventoryItemResponse.FromModel).ToList()
|
||||
});
|
||||
}
|
||||
|
||||
[HttpPost("by-owner/{ownerType}/{ownerId}/move")]
|
||||
[Authorize(Roles = "USER,SUPER")]
|
||||
public async Task<IActionResult> Move(string ownerType, string ownerId, [FromBody] MoveInventoryItemRequest req)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(req.ItemId))
|
||||
return BadRequest("itemId required");
|
||||
if (req.ToSlot < 0)
|
||||
return BadRequest("toSlot must be >= 0");
|
||||
if (req.Quantity is <= 0)
|
||||
return BadRequest("quantity must be greater than 0");
|
||||
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
return Unauthorized();
|
||||
|
||||
var access = await _inventory.ResolveOwnerAsync(ownerType, ownerId, userId, User.IsInRole("SUPER"));
|
||||
if (!access.IsSupported)
|
||||
return BadRequest("Unsupported ownerType");
|
||||
if (!access.Exists)
|
||||
return NotFound();
|
||||
if (!access.IsAuthorized)
|
||||
return Forbid();
|
||||
|
||||
var result = await _inventory.MoveAsync(access, req);
|
||||
return result.Status switch
|
||||
{
|
||||
InventoryMutationStatus.ItemNotFound => NotFound(),
|
||||
InventoryMutationStatus.Invalid => BadRequest("Invalid move"),
|
||||
InventoryMutationStatus.Conflict => Conflict("Target slot is not available"),
|
||||
_ => Ok(new InventoryOwnerResponse
|
||||
{
|
||||
OwnerType = access.OwnerType,
|
||||
OwnerId = access.OwnerId,
|
||||
Items = result.Items.Select(InventoryItemResponse.FromModel).ToList()
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("transfer")]
|
||||
[Authorize(Roles = "USER,SUPER")]
|
||||
public async Task<IActionResult> Transfer([FromBody] TransferInventoryItemRequest req)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(req.ItemId))
|
||||
return BadRequest("itemId required");
|
||||
if (string.IsNullOrWhiteSpace(req.FromOwnerType) || string.IsNullOrWhiteSpace(req.FromOwnerId))
|
||||
return BadRequest("from owner required");
|
||||
if (string.IsNullOrWhiteSpace(req.ToOwnerType) || string.IsNullOrWhiteSpace(req.ToOwnerId))
|
||||
return BadRequest("to owner required");
|
||||
if (req.ToSlot is < 0)
|
||||
return BadRequest("toSlot must be >= 0");
|
||||
if (req.Quantity is <= 0)
|
||||
return BadRequest("quantity must be greater than 0");
|
||||
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
return Unauthorized();
|
||||
|
||||
var fromAccess = await _inventory.ResolveOwnerAsync(req.FromOwnerType, req.FromOwnerId, userId, User.IsInRole("SUPER"));
|
||||
if (!fromAccess.IsSupported)
|
||||
return BadRequest("Unsupported fromOwnerType");
|
||||
if (!fromAccess.Exists)
|
||||
return NotFound("Source owner not found");
|
||||
if (!fromAccess.IsAuthorized)
|
||||
return Forbid();
|
||||
|
||||
var toAccess = await _inventory.ResolveOwnerAsync(req.ToOwnerType, req.ToOwnerId, userId, User.IsInRole("SUPER"));
|
||||
if (!toAccess.IsSupported)
|
||||
return BadRequest("Unsupported toOwnerType");
|
||||
if (!toAccess.Exists)
|
||||
return NotFound("Target owner not found");
|
||||
if (!toAccess.IsAuthorized)
|
||||
return Forbid();
|
||||
|
||||
var result = await _inventory.TransferAsync(fromAccess, toAccess, req);
|
||||
return result.Status switch
|
||||
{
|
||||
InventoryMutationStatus.ItemNotFound => NotFound(),
|
||||
InventoryMutationStatus.Invalid => BadRequest("Invalid transfer"),
|
||||
InventoryMutationStatus.Conflict => Conflict("Target slot is not available"),
|
||||
_ => Ok(new TransferInventoryResponse
|
||||
{
|
||||
MovedItemId = req.ItemId,
|
||||
FromOwnerType = fromAccess.OwnerType,
|
||||
FromOwnerId = fromAccess.OwnerId,
|
||||
ToOwnerType = toAccess.OwnerType,
|
||||
ToOwnerId = toAccess.OwnerId,
|
||||
FromItems = result.Items.Select(InventoryItemResponse.FromModel).Where(x => x.OwnerType == fromAccess.OwnerType && x.OwnerId == fromAccess.OwnerId).ToList(),
|
||||
ToItems = result.Items.Select(InventoryItemResponse.FromModel).Where(x => x.OwnerType == toAccess.OwnerType && x.OwnerId == toAccess.OwnerId).ToList()
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("items/{itemId}/consume")]
|
||||
[Authorize(Roles = "USER,SUPER")]
|
||||
public async Task<IActionResult> Consume(string itemId, [FromBody] ConsumeInventoryItemRequest req)
|
||||
{
|
||||
if (req.Quantity <= 0)
|
||||
return BadRequest("quantity must be greater than 0");
|
||||
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
return Unauthorized();
|
||||
|
||||
var result = await _inventory.ConsumeAsync(itemId, req.Quantity, userId, User.IsInRole("SUPER"));
|
||||
return result.Status switch
|
||||
{
|
||||
InventoryMutationStatus.ItemNotFound => NotFound(),
|
||||
InventoryMutationStatus.Invalid => BadRequest("Invalid consume request"),
|
||||
InventoryMutationStatus.Conflict => Conflict(),
|
||||
_ => Ok(new InventoryOwnerResponse
|
||||
{
|
||||
OwnerType = result.OwnerType,
|
||||
OwnerId = result.OwnerId,
|
||||
Items = result.Items.Select(InventoryItemResponse.FromModel).ToList()
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("items/{itemId}/equip")]
|
||||
[Authorize(Roles = "USER,SUPER")]
|
||||
public async Task<IActionResult> Equip(string itemId, [FromBody] EquipInventoryItemRequest req)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(req.OwnerId))
|
||||
return BadRequest("ownerId required");
|
||||
if (string.IsNullOrWhiteSpace(req.EquipmentSlot))
|
||||
return BadRequest("equipmentSlot required");
|
||||
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
return Unauthorized();
|
||||
|
||||
var result = await _inventory.EquipAsync(itemId, req.OwnerId, req.EquipmentSlot, userId, User.IsInRole("SUPER"));
|
||||
return result.Status switch
|
||||
{
|
||||
InventoryMutationStatus.ItemNotFound => NotFound(),
|
||||
InventoryMutationStatus.Invalid => BadRequest("Invalid equip request"),
|
||||
InventoryMutationStatus.Conflict => Conflict("Equipment slot is not available"),
|
||||
_ => Ok(new InventoryOwnerResponse
|
||||
{
|
||||
OwnerType = result.OwnerType,
|
||||
OwnerId = result.OwnerId,
|
||||
Items = result.Items.Select(InventoryItemResponse.FromModel).ToList()
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
[HttpPost("items/{itemId}/unequip")]
|
||||
[Authorize(Roles = "USER,SUPER")]
|
||||
public async Task<IActionResult> Unequip(string itemId, [FromBody] UnequipInventoryItemRequest req)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(req.OwnerId))
|
||||
return BadRequest("ownerId required");
|
||||
if (req.PreferredSlot is < 0)
|
||||
return BadRequest("preferredSlot must be >= 0");
|
||||
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
if (string.IsNullOrWhiteSpace(userId))
|
||||
return Unauthorized();
|
||||
|
||||
var result = await _inventory.UnequipAsync(itemId, req.OwnerId, req.PreferredSlot, userId, User.IsInRole("SUPER"));
|
||||
return result.Status switch
|
||||
{
|
||||
InventoryMutationStatus.ItemNotFound => NotFound(),
|
||||
InventoryMutationStatus.Invalid => BadRequest("Invalid unequip request"),
|
||||
InventoryMutationStatus.Conflict => Conflict("Inventory slot is not available"),
|
||||
_ => Ok(new InventoryOwnerResponse
|
||||
{
|
||||
OwnerType = result.OwnerType,
|
||||
OwnerId = result.OwnerId,
|
||||
Items = result.Items.Select(InventoryItemResponse.FromModel).ToList()
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user