Skip to content

Commit

Permalink
FEAT: Include a Product entity with pictures for sampling anonymous e…
Browse files Browse the repository at this point in the history
…ndpoints and downloading (#61)

## Description
Include a Product entity with pictures for sampling anonymous endpoints
and upload/download of files.

## Related Issue
Closes #52 

## How Has This Been Tested?
Template flag `--filesSupport` has been changed by
`--excludeFilesSupport`, which will default to true and will include the
implementation of the Products and Files by default and allows the user
to opt-out.
All the files and code related to Products and Files should be excluded
when passing the `--excludeFilesSupport` flag during the creation of a
new solution.

## Screenshots (if appropriate):

## Types of changes
- [ ] Bug fix (non-breaking change which fixes an issue)
- [X] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)

## Checklist:
<!--- Go over all the following points, and put an `x` in all the boxes
that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
- [X] My code follows the code style of this project.
- [X] My change requires a change to the documentation.
- [x] I have updated the documentation accordingly.
- [X] I have read the **CONTRIBUTING** document.
- [X] I have added tests to cover my changes.
- [X] All new and existing tests passed.
  • Loading branch information
CesarD authored Dec 23, 2023
1 parent 32a6128 commit fb6a183
Show file tree
Hide file tree
Showing 110 changed files with 4,286 additions and 1,214 deletions.
4 changes: 2 additions & 2 deletions src/Content/Backend/Solution/.template.config/ide.host.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
"isVisible": true
},
{
"id": "filesSupport",
"id": "excludeFilesSupport",
"name": {
"text": "Include files support and structure"
"text": "Exclude files support and structure"
},
"isVisible": true
},
Expand Down
113 changes: 75 additions & 38 deletions src/Content/Backend/Solution/.template.config/template.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@
"displayName": "Exclude Common projects",
"description": "Exclude all the Common.* projects from the solution generated"
},
"filesSupport": {
"excludeFilesSupport": {
"type": "parameter",
"datatype": "bool",
"defaultValue": "false",
"displayName": "Include files support and structure",
"description": "Include support for Azure BlobStorage and file handling structure"
"displayName": "Exclude files support and structure",
"description": "Exclude support for Azure BlobStorage and file handling structure"
},
"massTransitIntegration": {
"type": "parameter",
Expand Down Expand Up @@ -144,7 +144,9 @@
"**/*.filelist",
"**/*.user",
"**/*.lock.json",
"**/.vs/**/*"
"**/.vs/**/*",
"**/logs/**",
"**/TestResults/**"
],
"modifiers": [
{
Expand All @@ -156,25 +158,43 @@
]
},
{
"condition": "(!filesSupport)",
"condition": "(excludeFilesSupport)",
"exclude": [
"Monaco.Template.Backend.Common.BlobStorage/**/*",
"Monaco.Template.Backend.Common.BlobStorage.Tests/**/*",
"Monaco.Template.Backend.Api/Controllers/FilesController.cs",
"Monaco.Template.Backend.Api/Controllers/ImagesController.cs",
"Monaco.Template.Backend.Api/Controllers/ProductsController.cs",
"Monaco.Template.Backend.Api/DTOs/ProductCreateEditDto.cs",
"Monaco.Template.Backend.Api/DTOs/Extensions/ProductExtensions.cs",
"Monaco.Template.Backend.Application/Features/File/**/*",
"Monaco.Template.Backend.Application/Features/Image/**/*",
"Monaco.Template.Backend.Application/Features/Product/**/*",
"Monaco.Template.Backend.Application/DTOs/Extensions/FileExtensions.cs",
"Monaco.Template.Backend.Application/DTOs/File*.cs",
"Monaco.Template.Backend.Application/DTOs/Extensions/ProductExtensions.cs",
"Monaco.Template.Backend.Application/DTOs/FileDto.cs",
"Monaco.Template.Backend.Application/DTOs/ImageDto.cs",
"Monaco.Template.Backend.Application/DTOs/ProductDto.cs",
"Monaco.Template.Backend.Application/Services/**/*FileService.*",
"Monaco.Template.Backend.Application.Infrastructure/EntityConfigurations/DocumentEntityConfiguration.cs",
"Monaco.Template.Backend.Application.Infrastructure/EntityConfigurations/FileEntityConfiguration.cs",
"Monaco.Template.Backend.Application.Infrastructure/EntityConfigurations/ImageEntityConfiguration.cs",
"Monaco.Template.Backend.Application.Infrastructure/EntityConfigurations/ProductEntityConfiguration.cs",
"Monaco.Template.Backend.Application.Tests/Services/FileServiceTests.cs",
"Monaco.Template.Backend.Application.Tests/Features/File/**/*",
"Monaco.Template.Backend.Application.Tests/Features/Product/**/*",
"Monaco.Template.Backend.Common.Tests/Factories/Entities/DocumentFactory.cs",
"Monaco.Template.Backend.Common.Tests/Factories/Entities/ImageFactory.cs",
"Monaco.Template.Backend.Common.Tests/Factories/Entities/ProductFactory.cs",
"Monaco.Template.Backend.Domain/Model/Document.cs",
"Monaco.Template.Backend.Domain/Model/File.cs",
"Monaco.Template.Backend.Domain/Model/Image.cs"
"Monaco.Template.Backend.Domain/Model/GpsPosition.cs",
"Monaco.Template.Backend.Domain/Model/Image.cs",
"Monaco.Template.Backend.Domain/Model/ImageDimensions.cs",
"Monaco.Template.Backend.Domain/Model/Product.cs",
"Monaco.Template.Backend.Domain.Tests/DocumentTests.cs",
"Monaco.Template.Backend.Domain.Tests/GpsPositionTests.cs",
"Monaco.Template.Backend.Domain.Tests/ImageDimensionsTests.cs",
"Monaco.Template.Backend.Domain.Tests/ImageTests.cs",
"Monaco.Template.Backend.Domain.Tests/ProductTests.cs"
]
},
{
Expand Down Expand Up @@ -205,12 +225,11 @@
}
],
"guids": [
"8ac1d4e3-61ef-452f-a386-ff3ec448fbff",
"4c76f225-faad-42ec-801b-9ad3b505b7f5",
"1095fb23-b2a1-4fd6-bc12-433529eea56e",
"8bfe9c37-2620-4156-88b8-286537954c5e",
"35484293-234f-40da-b430-a95170ede449",
"29dfbc35-3da6-4c68-aa97-5cce06d80917",
"9a19103f-16f7-4668-be54-9a1e7a4f7556",
"426a6ab4-95f6-46ac-ab6d-98c4612f74e5",
"78120def-b581-4d6b-92d7-1735070acb7f",
"bfd5f082-8402-45de-8aba-ebb354bd2858",
Expand All @@ -230,11 +249,10 @@
"71313461-6a79-47b3-aeb9-5668a88935f2",
"1b80e15b-fc20-4b57-a3e5-3b6b3ebda92f",
"42e51d47-b82f-4a92-b1e5-cd8be44de6f0",
"d8623b90-59c1-4753-a0e6-f2dbd4305c9b",
"42c5f44e-1221-43df-a6f5-4cb2cbef8d72",
"eda2cf1e-7707-458d-b91b-956b9a9be260",
"80c3602f-f30d-4f1c-83f4-3e8395bdce25",
"c11e0fa2-baf7-44ae-9db9-28ce239042b6",
"b0464d8d-2dbd-461a-9861-38c0747b23a6",
"95c05d66-9802-411a-9f82-4b9ab0b34685",
"4a5cb9f2-340b-483c-83d7-7324fc61cde4",
"05648945-7e90-42ec-a4dc-233fd52cddfe",
Expand Down Expand Up @@ -263,13 +281,16 @@
"9ec31276-3997-49d7-a842-0a36564a180d",
"d34a41a6-7c64-408a-a378-3df70edc20d9",
"9522c83e-dbc9-4fde-a61f-9a37a5ab89ee",
"7d7112cb-ffed-4b52-b440-3fdbd7a63c5a",
"c443d55b-32e6-47e9-a057-96a7eab1d688",
"4857a3cf-f3b0-48ac-94cc-3b2384696b44",
"6c345596-0966-47ed-b41b-6ba41319908c",
"2a0fe481-1bc6-4fa4-a02d-0aace321c60e",
"cc450c6d-bf28-45e4-9148-6bb7d4187641",
"53405b4d-d952-47d8-9bc7-8f52a15522e8",
"4aee08a5-4691-4a57-9d87-e02dc59fe3ab",
"ed97a0b3-c82c-471f-89dc-b48e738381fa",
"a1a76a9c-e22e-4e5a-aeec-e71b381ca77e",
"cc450c6d-bf28-45e4-9148-6bb7d4187641",
"b6049a46-fbd1-4368-a72b-364c284f01e0",
"09fb98e3-c6c4-4151-bf3c-1fbc804b080e",
"4cd869a0-9d32-41d7-9769-e611a48cd9a9",
Expand All @@ -287,6 +308,10 @@
"d5d68e01-42f1-488c-ab96-471596a2b750",
"7149fad9-2c54-4b91-975b-e893f9a3d094",
"c385dd5b-f501-4fb6-8b16-f381618d090a",
"33ff4854-2aad-4b12-9701-472d0a470c4f",
"805aea0c-522f-4040-b380-c0dac6f55245",
"194ef116-fa08-407a-b535-1d5a60356c7e",
"a0f31e04-653c-4783-8bb0-d4a689c1a36e",
"d07a981d-4198-4f2c-be6c-acddc3aa98d3",
"1a374de2-4ee9-4869-902a-12f53ad70a45",
"070fdddb-0a0a-4a2c-b655-6111c2d653dc",
Expand Down Expand Up @@ -328,33 +353,46 @@
"160cb3d9-53e2-42e4-bc12-4437386c6367",
"6cd2e74a-bf15-4eb2-9e61-f96ff1469358",
"8511446d-af34-4a9f-935d-38ab0a062688",
"e0705766-2e91-4735-b9fa-8590bc4faae9",
"c8675fd0-5ddb-4628-82d4-fb063859505e",
"d686d005-b309-4551-bfb1-d71a4f6e0d11",
"7f4c80ee-159d-4ae4-b928-47ac3684d45b",
"0c134675-a8e6-4146-a67e-bdd048197008",
"362c21ef-ac96-43cf-8aba-51e4e16bfa25",
"2533aeba-e2b1-41c4-9d1a-a07cd95fbc18",
"e0a5b338-b3b0-41cf-ae0f-cc4cabe5c1f2",
"b1dbc131-9a1b-4a9c-a985-b7fb4d2a0127",
"adef851f-c566-4eb1-bd8a-692cd3a37704",
"fec3ed3d-3aef-48d2-a699-ed31349121da",
"d5c72026-48b1-4b49-86e3-160fb70fd05a",
"feaf9331-9f7a-4143-9247-27a0ea83f7e9",
"c0336213-5b51-431b-b324-67f774557d54",
"10ce57b2-2a55-43de-914a-56c517f43242",
"c87701f8-addf-44e1-a630-113b6a1871ca",
"dd4429b1-7ecc-4239-9ee3-6dc0c57c7492",
"0d500e1f-2389-45d0-8603-45ff007e0314",
"92d80a4c-c3c1-4a81-a72d-6044516e63f7",
"e05767a5-c141-4f01-b7a2-4efb5e2a26a3",
"82f114ba-9845-4838-9a3b-83bc743050bd",
"f8db2596-279d-4254-b6fe-1b8224d9aee5",
"205ad146-f5c4-4e7a-9419-8a2ea73b19d4",
"547e2363-08f5-4f67-9d5a-fed1bc883af8",
"d3d92cbf-7dea-404b-9b3b-e0e01d01b181",
"d10429c7-e0b3-47a9-ad34-a99eb2c1ae0d",
"718b5472-a9bb-4dba-a1c5-e48f8f5020e5",
"fa17826b-1ce9-4ec0-bff5-da0e1754ab7b",
"ab73883d-7755-458c-99b1-daed2e7d1fc7",
"b3df1fee-f37f-4bff-a6e6-b801324228f0",
"e38db072-8687-40eb-a35b-f9c375da1e01",
"83845f6b-6f32-43db-9de3-71299b05a7ee",
"39089091-f930-4d29-b20c-14e2a7a3a861",
"dfe90700-c265-49d6-8cdc-23855b75ef03",
"1c1a942e-ec7d-4312-aa4f-f0a571da0bce",
"6d7fab52-2a08-46ed-8a19-fe27284baa47",
"fc94d7d8-5d72-47e6-a4de-4c1512d71e16",
"6d7a94da-fbb7-4d20-b41c-472bed514830",
"c5d70775-bdc7-4826-93b1-0ba233ed4e7e",
"9b95767e-b8c7-4570-961d-13e8e59aae7c",
"d7b400a1-9455-46e1-8322-10ce0a3cbd07",
"39c225ca-9d35-42f9-b535-f477b40182df",
"54c70413-4884-4178-a662-96440d3dca17",
"f053015e-b577-42fa-9cd1-5b723eecb72c",
"8ac1d4e3-61ef-452f-a386-ff3ec448fbff",
"4c76f225-faad-42ec-801b-9ad3b505b7f5",
"c176b6ce-f931-4ad5-a61e-dad4a01180e6",
"2281fe14-3548-4060-b503-3b26bcfd0000",
"1724c39a-e51c-46bb-9db9-1227e9edd406",
"30b0dc89-e29c-4867-a17d-3af74695ecc0",
"0ebc0704-58e0-4202-8cbb-d818a3fdfb5a",
"a2fe74e1-b743-11d0-ae1a-00a0c90fffc3",
"90a6b3a7-c1a3-4009-a288-e2ff89e96fa0",
"a6c744a8-0e4a-4fc6-886a-064283054674",
"1fc202d4-d401-403c-9834-5b218574bb67",
"13b12e3e-c1b4-4539-9371-4fe9a0d523fc",
"116d2292-e37d-41cd-a077-ebacac4c8cc4",
"aa2115a1-9712-457b-9047-dbb71ca2cdd2",
"0174dea2-fdbe-4ef1-8f99-c0beae78880f",
"75188d03-9892-4ae2-abf1-207126247ce5",
"1c4feeaa-4718-4aa9-859d-94ce25d182ba",
"ae27a6b0-e345-4288-96df-5eaf394ee369",
"5c064eff-a037-a6a3-06ec-92f662903af3",
"a8b54a61-35d8-9b82-76e4-c709561d9952",
"9f420922-9842-0d2d-616d-dacee7c25db7",
Expand Down Expand Up @@ -549,7 +587,6 @@
"5a3893d1-1e36-310c-7633-8f36ffa26315",
"a2689ae3-3643-6250-a748-8f055cc72da8",
"be447a08-0a85-5779-8c65-cf15c2c9a5a8",
"c776f397-182b-6d0d-09f2-4e440dc093d3",
"d8623b90-59c1-4753-a0e6-f2dbd4305c9b"
"c776f397-182b-6d0d-09f2-4e440dc093d3"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ public static class Scopes
{
public const string CompaniesRead = "companies:read";
public const string CompaniesWrite = "companies:write";
#if filesSupport
public const string FilesRead = "files:read";
#if (!excludeFilesSupport)
public const string FilesWrite = "files:write";
#endif
public const string ProductsWrite = "products:write";
#endif

public static List<string> List => new()
{
CompaniesRead,
CompaniesWrite,
#if filesSupport
FilesRead,
FilesWrite
#endif
};
public static List<string> List =>
[
CompaniesRead,
CompaniesWrite,
#if (!excludeFilesSupport)
FilesWrite,
ProductsWrite
#endif
];
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,35 @@ public CompaniesController(IMediator mediator)
_mediator = mediator;
}

/// <summary>
/// Gets a list of companies
/// </summary>
/// <returns></returns>
[HttpGet]
#if (!disableAuth)
[Authorize(Scopes.CompaniesRead)]
#endif
public Task<ActionResult<Page<CompanyDto>>> Get() =>
_mediator.ExecuteQueryAsync(new GetCompanyPage.Query(Request.Query));

/// <summary>
/// Gets a company by Id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("{id:guid}")]
#if (!disableAuth)
[Authorize(Scopes.CompaniesRead)]
#endif
public Task<ActionResult<CompanyDto?>> Get(Guid id) =>
_mediator.ExecuteQueryAsync(new GetCompanyById.Query(id));

/// <summary>
/// Creates a new company
/// </summary>
/// <param name="apiVersion"></param>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPost]
#if (!disableAuth)
[Authorize(Scopes.CompaniesWrite)]
Expand All @@ -52,6 +67,12 @@ public Task<ActionResult<Guid>> Post([FromRoute] ApiVersion apiVersion, [FromBod
"api/v{0}/Companies/{1}",
apiVersion);

/// <summary>
/// Edits an existing company
/// </summary>
/// <param name="id"></param>
/// <param name="dto"></param>
/// <returns></returns>
[HttpPut("{id:guid}")]
#if (!disableAuth)
[Authorize(Scopes.CompaniesWrite)]
Expand All @@ -61,6 +82,11 @@ public Task<IActionResult> Put(Guid id, [FromBody] CompanyCreateEditDto dto) =>
ModelState,
ResponseType.NoContent);

/// <summary>
/// Deletes a company
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpDelete("{id:guid}")]
#if (!disableAuth)
[Authorize(Scopes.CompaniesWrite)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
#if filesSupport
#if (!excludeFilesSupport)
#if (!disableAuth)
using Monaco.Template.Backend.Api.Auth;
#endif
using Monaco.Template.Backend.Application.DTOs;
using Monaco.Template.Backend.Application.Features.File;
using Monaco.Template.Backend.Common.Api.Application;
using MediatR;
#if (!disableAuth)
using Microsoft.AspNetCore.Authorization;
#endif
using Microsoft.AspNetCore.Mvc;
using System.Net;
using Asp.Versioning;

namespace Monaco.Template.Backend.Api.Controllers;
Expand All @@ -26,6 +24,12 @@ public FilesController(IMediator mediator)
_mediator = mediator;
}

/// <summary>
/// Uploads a new file that remains as temporal until it is referenced somewhere else in the app
/// </summary>
/// <param name="apiVersion"></param>
/// <param name="file"></param>
/// <returns></returns>
[HttpPost]
#if (!disableAuth)
[Authorize(Scopes.FilesWrite)]
Expand All @@ -35,36 +39,5 @@ public Task<ActionResult<Guid>> Post([FromRoute] ApiVersion apiVersion, [FromFor
ModelState,
"api/v{0}/files/{1}",
apiVersion);

[HttpGet("{id:guid}")]
#if (!disableAuth)
[Authorize(Scopes.FilesRead)]
#endif
public Task<ActionResult<FileDto>> Get(Guid id) =>
_mediator.ExecuteQueryAsync(new GetFileById.Query(id));

[HttpGet("{id:guid}/Download")]
#if (!disableAuth)
[Authorize(Scopes.FilesRead)]
#endif
[ProducesResponseType(typeof(FileContentResult), (int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task<IActionResult> Download(Guid id)
{
var result = await _mediator.Send(new DownloadFileById.Query(id));

if (result == null)
return NotFound();

return File(result.FileContent, result.ContentType, result.FileName);
}

[HttpDelete("{id:guid}")]
#if (!disableAuth)
[Authorize(Scopes.FilesWrite)]
#endif
public Task<IActionResult> Delete(Guid id) =>
_mediator.ExecuteCommandAsync(new DeleteFile.Command(id),
ModelState);
}
#endif
Loading

0 comments on commit fb6a183

Please sign in to comment.