Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
3f2e207
Feature: Fork do repositório, criação das pastas principais do projeto
gabrieldeoliveira04 Jan 10, 2026
123d895
Feature: configuração da chave(hardcoded) JWT para autenticação de us…
gabrieldeoliveira04 Jan 10, 2026
cad5e27
Feature: Criação do AuthController, responsável pela validação dos da…
gabrieldeoliveira04 Jan 10, 2026
60516bb
Feature: Exclusão do template padrão do program.cs gerado pelo .net
gabrieldeoliveira04 Jan 10, 2026
1c1f63b
Correção do nome do arquivo AuthController, instalação das libraries,…
gabrieldeoliveira04 Jan 10, 2026
d8b2aee
Feature: correção de pacotes e mudança do projeto para .net9 (o padrã…
gabrieldeoliveira04 Jan 10, 2026
f6e144e
Feature:instalação dos pacotes para adição de comentários no schema, …
gabrieldeoliveira04 Jan 10, 2026
19945d5
Correção de comentários
gabrieldeoliveira04 Jan 10, 2026
823fa27
Feature: criação da entidade Book
gabrieldeoliveira04 Jan 10, 2026
9116416
Feature: criação do dbbcontext e adição da entidade book ao mesmo com…
gabrieldeoliveira04 Jan 10, 2026
652b6ac
Feature: criação da interface book, com paginação e filtro implementados
gabrieldeoliveira04 Jan 10, 2026
7e3f93a
Feature: Criação do service e do controller
gabrieldeoliveira04 Jan 10, 2026
e132c39
Feature: Conexão das pastas criadas ao program.cs
gabrieldeoliveira04 Jan 10, 2026
78663e8
Feature: definição da default connection
gabrieldeoliveira04 Jan 12, 2026
07ebfd1
Fix: correção de versões e exclusão de pastas padrões
gabrieldeoliveira04 Jan 12, 2026
4551cc1
Feature: criação dos dtos de request e response dos books
gabrieldeoliveira04 Jan 12, 2026
ce151ae
Fix: Correção dos services de busca por id e ordenação
gabrieldeoliveira04 Jan 12, 2026
23feb8b
fix: correção de versões, necessária tendo em vista que o projeto foi…
gabrieldeoliveira04 Jan 12, 2026
28936ee
Feature: Adição de pesquisa pelo nome do livro
gabrieldeoliveira04 Jan 12, 2026
48f07fc
Build funcional
gabrieldeoliveira04 Jan 12, 2026
c8520bc
Fix: Refinamento do bookrequest para melhor compreensão nos schemas
gabrieldeoliveira04 Jan 12, 2026
c3bd06e
Fix:Refinamento do bookresponse para melhor compreensão nos schemas
gabrieldeoliveira04 Jan 12, 2026
75c8676
fix; pesquisa por nome
gabrieldeoliveira04 Jan 12, 2026
9195f02
Feature:Criação do gitignore
gabrieldeoliveira04 Jan 13, 2026
b0476c7
Fix: correções de inconsistências
gabrieldeoliveira04 Jan 13, 2026
b6bed6b
fix: validação de autor
gabrieldeoliveira04 Jan 13, 2026
b6e1c39
fix: schemas e comentários do swagger
gabrieldeoliveira04 Jan 13, 2026
8e27b18
Feature: troca de banco de dados para postgreesql para deploy no render
gabrieldeoliveira04 Jan 13, 2026
982b5f8
fix:ajuste de root no dockerfile
gabrieldeoliveira04 Jan 13, 2026
df4151e
fix: dockerfile configurado para acessar cada projeto individualmente
gabrieldeoliveira04 Jan 13, 2026
6a4a358
fix: ajuste de versões
gabrieldeoliveira04 Jan 13, 2026
7509dc3
fix: root no dockefile
gabrieldeoliveira04 Jan 13, 2026
080f325
fix: connection string retirada do local para ser lida pelo ambiente …
gabrieldeoliveira04 Jan 13, 2026
3613e72
fix: connection string indo vazia para o render
gabrieldeoliveira04 Jan 13, 2026
3e815d0
fix: get com paginação dando erro
gabrieldeoliveira04 Jan 13, 2026
aac5aff
cfix: correção de banco
gabrieldeoliveira04 Jan 13, 2026
9f4b972
Feature: tanto no server local quanto na produção o swagger abre auto…
gabrieldeoliveira04 Jan 13, 2026
b0f6607
finalizado
gabrieldeoliveira04 Jan 13, 2026
7669fdf
fix: atualização do readme
gabrieldeoliveira04 Jan 14, 2026
1160ed5
Feature: paginação mostrando elementos por página e número de página
gabrieldeoliveira04 Jan 14, 2026
d0e55dd
fix: atualização do pull request
gabrieldeoliveira04 Jan 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Binary file added Curriculo_Fullstack.pdf
Binary file not shown.
36 changes: 36 additions & 0 deletions ProjectLibrary/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Build results
bin/
obj/

# SQLite files (não vamos mais usar)
*.db
*.sqlite
*.sqlite3

# Publish output
publish/
out/

# VS / JetBrains
.vs/
.vscode/
.idea/

# User-specific
*.user
*.suo
*.userosscache
*.sln.docstates

# Logs
*.log

# Environment / secrets
.env
appsettings.Development.json
appsettings.Local.json

# OS files
.DS_Store
Thumbs.db

34 changes: 34 additions & 0 deletions ProjectLibrary/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Etapa 1: build
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app

# Copia os projetos
COPY DoroTech.BookStore.API/*.csproj ./DoroTech.BookStore.API/
COPY DoroTech.BookStore.Application/*.csproj ./DoroTech.BookStore.Application/
COPY DoroTech.BookStore.Domain/*.csproj ./DoroTech.BookStore.Domain/
COPY DoroTech.BookStore.Infrastructure/*.csproj ./DoroTech.BookStore.Infrastructure/

# Restore individual
RUN dotnet restore DoroTech.BookStore.API/DoroTech.BookStore.API.csproj
RUN dotnet restore DoroTech.BookStore.Application/DoroTech.BookStore.Application.csproj
RUN dotnet restore DoroTech.BookStore.Domain/DoroTech.BookStore.Domain.csproj
RUN dotnet restore DoroTech.BookStore.Infrastructure/DoroTech.BookStore.Infrastructure.csproj


# Copia tudo e publica
COPY . .
WORKDIR /app/DoroTech.BookStore.API
RUN dotnet publish DoroTech.BookStore.API.csproj -c Release -o out


# Etapa 2: runtime
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/DoroTech.BookStore.API/out ./


# Porta exposta
EXPOSE 80

# Entry point
ENTRYPOINT ["dotnet", "DoroTech.BookStore.API.dll"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using DoroTech.BookStore.API.Models;
using Swashbuckle.AspNetCore.Annotations;

namespace DoroTech.BookStore.API.Controllers;

[ApiController]
[Route("api/auth")]
public class AuthController : ControllerBase
{
private readonly IConfiguration _configuration;

public AuthController(IConfiguration configuration)
{
_configuration = configuration;
}

/// Realiza o Login do Administrador e retorna um token JWT que é usado para autenticação e acesso dos endpoints privados
/// <param name="request">Credenciais do administrador</param>
/// <returns>Token JWT</returns>
[HttpPost("login")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(object))]
[ProducesResponseType(StatusCodes.Status401Unauthorized, Type = typeof(ProblemDetails))]
[SwaggerOperation(
Summary = "Login do administrador",
Description = "Recebe usuário e senha, valida e retorna token JWT válido por 2 horas"
)]
public IActionResult Login([FromBody] LoginRequest request)
{
var adminUser = _configuration["Jwt:AdminUser"];
var adminPassword = _configuration["Jwt:AdminPassword"];
// Váriaveis fixas para usuario e senha do admin, que estão contidas no appsettings.json

if (request.Username != adminUser || request.Password != adminPassword)
return Unauthorized("Usuário ou senha inválidos");
/// retorno de erro em caso de senha ou usuario inválido, Login: Usuário: "admin",Senha: "123456"

var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, request.Username),
new Claim(ClaimTypes.Role, "Admin"),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};

var key = new SymmetricSecurityKey(
Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]!)
);

var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(
issuer: _configuration["Jwt:Issuer"],
audience: _configuration["Jwt:Audience"],
claims: claims,
expires: DateTime.UtcNow.AddHours(2),
//tempo de expiração de login
signingCredentials: creds
);

return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token)
//Geração do token se os parâmetros anteriores forem atendidos
});
}
}
115 changes: 115 additions & 0 deletions ProjectLibrary/DoroTech.BookStore.API/Controllers/BooksController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using DoroTech.BookStore.Application.Services;
using DoroTech.BookStore.Domain.Entities;
using DoroTech.BookStore.Application.DTOs;
using Swashbuckle.AspNetCore.Annotations;

namespace DoroTech.BookStore.API.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class BooksController : ControllerBase
{
private readonly BookService _service;

public BooksController(BookService service)
{
_service = service;
}

//Lista todos os livros com paginação e filtro
[HttpGet]
[AllowAnonymous]
[ProducesResponseType(typeof(PagedResult<BookResponse>), StatusCodes.Status200OK)]
[SwaggerOperation(
Summary = "Lista livros",
Description = "Retorna livros paginados, opcionalmente filtrados por título (case-insensitive)."
)]
public async Task<IActionResult> GetAll(
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10,
[FromQuery] string? title = null)
{
var books = await _service.GetAllAsync(page, pageSize, title);
return Ok(books);
}

//filtra o livro pelo ID
[HttpGet("{id:guid}")]
[AllowAnonymous]
[ProducesResponseType(typeof(BookResponse), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> GetById(Guid id)
{
var book = await _service.GetByIdAsync(id);
return book is null ? NotFound() : Ok(book);
}

//Cria um novo livro(somente admin)
[HttpPost]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> Create([FromBody] BookRequest request)
{
if (!ModelState.IsValid)
return ValidationProblem(ModelState);

try
{
var id = await _service.CreateAsync(
request.Title,
request.Author,
request.Price,
request.Stock
);

return CreatedAtAction(nameof(GetById), new { id }, null);
}
catch (InvalidOperationException ex)
{
return BadRequest(new { error = ex.Message });
}
}


//Atualiza um livro existente (somente admin)
[HttpPut("{id:guid}")]
[Authorize(Roles = "Admin")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> Update(Guid id, [FromBody] BookRequest request)
{
if (!ModelState.IsValid)
return ValidationProblem(ModelState);

try
{
var updated = await _service.UpdateAsync(
id,
request.Title,
request.Author,
request.Price,
request.Stock
);

return updated ? NoContent() : NotFound("Livro não encontrado.");
}
catch (InvalidOperationException ex)
{
return Conflict(new { error = ex.Message });
}
}

//Deleta um livro pelo ID (somente admin)
[HttpDelete("{id:guid}")]
[Authorize(Roles = "Admin")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<IActionResult> Delete(Guid id)
{
var deleted = await _service.DeleteAsync(id);
return deleted ? NoContent() : NotFound("Livro não encontrado.");
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\DoroTech.BookStore.Application\DoroTech.BookStore.Application.csproj" />
<ProjectReference Include="..\DoroTech.BookStore.Infrastructure\DoroTech.BookStore.Infrastructure.csproj" />
</ItemGroup>

<ItemGroup>

<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.0" />

<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="8.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>

<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />

</ItemGroup>

</Project>



Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@DoroTech.BookStore.API_HostAddress = http://localhost:5221

GET {{DoroTech.BookStore.API_HostAddress}}/weatherforecast/
Accept: application/json

###
17 changes: 17 additions & 0 deletions ProjectLibrary/DoroTech.BookStore.API/Models/LoginRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using System.ComponentModel.DataAnnotations;
using Swashbuckle.AspNetCore.Annotations;

namespace DoroTech.BookStore.API.Models
{
public class LoginRequest
{
[Required]
[SwaggerSchema( "admin")] //valor incluido no schema do swagger
public string Username { get; set; } = string.Empty;

[Required]
[SwaggerSchema("123456")]//valor incluido no schema do swagger
public string Password { get; set; } = string.Empty;
}
}

Loading