From b924397f52c2df384d84691e674359994de3605e Mon Sep 17 00:00:00 2001 From: Eduardo Date: Mon, 9 Feb 2026 18:00:47 -0300 Subject: [PATCH] Docker aplicado --- .dockerignore | 11 +++++ Controllers/DevController.cs | 60 ------------------------ Controllers/WeatherForecastController.cs | 26 ---------- Dockerfile | 20 ++++++++ Program.cs | 37 +++++++++++---- WeatherForecast.cs | 13 ----- appsettings.Development.json | 17 +++++++ appsettings.json | 12 +++-- line-gestao-api.csproj | 12 ----- 9 files changed, 84 insertions(+), 124 deletions(-) create mode 100644 .dockerignore delete mode 100644 Controllers/DevController.cs delete mode 100644 Controllers/WeatherForecastController.cs create mode 100644 Dockerfile delete mode 100644 WeatherForecast.cs diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6fe783c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +.git +.github +.vs +bin +obj +**/bin +**/obj +*.user +*.suo +*.log +README.md diff --git a/Controllers/DevController.cs b/Controllers/DevController.cs deleted file mode 100644 index c6e0e2d..0000000 --- a/Controllers/DevController.cs +++ /dev/null @@ -1,60 +0,0 @@ -using line_gestao_api.Models; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; - -namespace line_gestao_api.Controllers; - -[ApiController] -[Route("dev")] -public class DevController : ControllerBase -{ - private readonly UserManager _userManager; - private readonly IConfiguration _config; - private readonly IWebHostEnvironment _env; - - public DevController( - UserManager userManager, - IConfiguration config, - IWebHostEnvironment env) - { - _userManager = userManager; - _config = config; - _env = env; - } - - /// - /// Reseta a senha do admin seeded (somente em Development). - /// - [HttpPost("reset-admin-password")] - public async Task ResetAdminPassword() - { - // 🔒 Proteção: só funciona em Development - if (!_env.IsDevelopment()) - return NotFound(); - - var email = (_config["Seed:AdminEmail"] ?? "admin@linegestao.local").Trim().ToLowerInvariant(); - var newPassword = _config["Seed:AdminPassword"] ?? "Admin123!"; - - var normalizedEmail = _userManager.NormalizeEmail(email); - - var user = await _userManager.Users - .FirstOrDefaultAsync(u => u.NormalizedEmail == normalizedEmail); - - if (user == null) - return NotFound("Admin não encontrado."); - - // remove lockout se existir (só pra garantir) - await _userManager.SetLockoutEndDateAsync(user, null); - await _userManager.ResetAccessFailedCountAsync(user); - - // reseta senha corretamente (via Identity) - var token = await _userManager.GeneratePasswordResetTokenAsync(user); - var reset = await _userManager.ResetPasswordAsync(user, token, newPassword); - - if (!reset.Succeeded) - return BadRequest(reset.Errors.Select(e => e.Description)); - - return Ok($"Senha do admin resetada com sucesso para: {newPassword}"); - } -} diff --git a/Controllers/WeatherForecastController.cs b/Controllers/WeatherForecastController.cs deleted file mode 100644 index 8974fec..0000000 --- a/Controllers/WeatherForecastController.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace line_gestao_api.Controllers -{ - [ApiController] - [Route("[controller]")] - public class WeatherForecastController : ControllerBase - { - private static readonly string[] Summaries = - [ - "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" - ]; - - [HttpGet(Name = "GetWeatherForecast")] - public IEnumerable Get() - { - return Enumerable.Range(1, 5).Select(index => new WeatherForecast - { - Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), - TemperatureC = Random.Shared.Next(-20, 55), - Summary = Summaries[Random.Shared.Next(Summaries.Length)] - }) - .ToArray(); - } - } -} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bdf7133 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src + +COPY ["line-gestao-api.csproj", "./"] +RUN dotnet restore "./line-gestao-api.csproj" + +COPY . . +RUN dotnet publish "./line-gestao-api.csproj" -c Release -o /app/publish /p:UseAppHost=false + +FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS final +WORKDIR /app + +ENV ASPNETCORE_URLS=http://+:8080 +ENV ASPNETCORE_ENVIRONMENT=Production + +COPY --from=build /app/publish . + +EXPOSE 8080 + +ENTRYPOINT ["dotnet", "line-gestao-api.dll"] diff --git a/Program.cs b/Program.cs index 6ce9b5a..8f52244 100644 --- a/Program.cs +++ b/Program.cs @@ -12,23 +12,34 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); -// ✅ Upload (Excel / multipart) builder.Services.Configure(o => { o.MultipartBodyLengthLimit = 50_000_000; }); -// ✅ CORS (Angular) +var corsOrigins = builder.Configuration + .GetSection("Cors:AllowedOrigins") + .Get()? + .Where(o => !string.IsNullOrWhiteSpace(o)) + .Select(o => o.Trim()) + .Distinct(StringComparer.OrdinalIgnoreCase) + .ToArray() + ?? []; + +if (corsOrigins.Length == 0) +{ + corsOrigins = ["http://localhost:4200"]; +} + builder.Services.AddCors(options => { options.AddPolicy("Front", p => - p.WithOrigins("http://localhost:4200") + p.WithOrigins(corsOrigins) .AllowAnyHeader() .AllowAnyMethod() ); }); -// ✅ EF Core (PostgreSQL) builder.Services.AddDbContext(options => options.UseNpgsql(builder.Configuration.GetConnectionString("Default")) ); @@ -49,12 +60,15 @@ builder.Services.AddIdentityCore(options => .AddEntityFrameworkStores() .AddDefaultTokenProviders(); -// ✅ Swagger builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); -// ✅ JWT -var jwtKey = builder.Configuration["Jwt:Key"]!; +var jwtKey = builder.Configuration["Jwt:Key"]; +if (string.IsNullOrWhiteSpace(jwtKey)) +{ + throw new InvalidOperationException("Configuration 'Jwt:Key' is required."); +} + var issuer = builder.Configuration["Jwt:Issuer"]; var audience = builder.Configuration["Jwt:Audience"]; @@ -89,18 +103,21 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(); } -app.UseHttpsRedirection(); +var useHttpsRedirection = builder.Configuration.GetValue("App:UseHttpsRedirection", !app.Environment.IsDevelopment()); +if (useHttpsRedirection) +{ + app.UseHttpsRedirection(); +} -// ✅ CORS antes de Auth app.UseCors("Front"); app.UseAuthentication(); app.UseMiddleware(); app.UseAuthorization(); -// ✅ SEED ANTES de subir controllers await SeedData.EnsureSeedDataAsync(app.Services); app.MapControllers(); +app.MapGet("/health", () => Results.Ok(new { status = "ok" })); app.Run(); diff --git a/WeatherForecast.cs b/WeatherForecast.cs deleted file mode 100644 index 5cefd28..0000000 --- a/WeatherForecast.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace line_gestao_api -{ - public class WeatherForecast - { - public DateOnly Date { get; set; } - - public int TemperatureC { get; set; } - - public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); - - public string? Summary { get; set; } - } -} diff --git a/appsettings.Development.json b/appsettings.Development.json index 2ed524a..1dedf75 100644 --- a/appsettings.Development.json +++ b/appsettings.Development.json @@ -1,4 +1,21 @@ { + "ConnectionStrings": { + "Default": "Host=localhost;Port=5432;Database=linegestao;Username=linegestao_app;Password=CHANGE_ME" + }, + "Jwt": { + "Key": "dev-only-please-replace-with-env-variable-in-production", + "Issuer": "LineGestao", + "Audience": "LineGestao", + "ExpiresMinutes": 360 + }, + "Cors": { + "AllowedOrigins": [ + "http://localhost:4200" + ] + }, + "App": { + "UseHttpsRedirection": false + }, "Logging": { "LogLevel": { "Default": "Information", diff --git a/appsettings.json b/appsettings.json index 7b7b12f..381f9cf 100644 --- a/appsettings.json +++ b/appsettings.json @@ -1,13 +1,19 @@ { "ConnectionStrings": { - "Default": "Host=localhost;Port=5432;Database=linegestao;Username=linegestao_app;Password=255851Ed@" + "Default": "Host=localhost;Port=5432;Database=linegestao;Username=linegestao_app;Password=CHANGE_ME" }, "Jwt": { - "Key": "vI8/oEYEWN5sBDTisNuZFjZAl+YFvXEJ96POb73/eoq3NaFPkOFXyPRdf/HWGAFnUsF3e3QpYL6Wl4Bc2v+l3g==", + "Key": "", "Issuer": "LineGestao", "Audience": "LineGestao", "ExpiresMinutes": 360 }, + "Cors": { + "AllowedOrigins": [ "http://localhost:4200" ] + }, + "App": { + "UseHttpsRedirection": true + }, "Notifications": { "CheckIntervalMinutes": 60, "ReminderDays": [30, 15, 7] @@ -16,6 +22,6 @@ "DefaultTenantName": "Default", "AdminName": "Administrador", "AdminEmail": "admin@linegestao.local", - "AdminPassword": "Admin123!" + "AdminPassword": "CHANGE_ME" } } diff --git a/line-gestao-api.csproj b/line-gestao-api.csproj index 2577bc3..9fddb98 100644 --- a/line-gestao-api.csproj +++ b/line-gestao-api.csproj @@ -10,13 +10,6 @@ false - - - - - - - @@ -24,11 +17,6 @@ - - - - -