From 304e7bf5f52d2f19c84acec4393e9b8607f1c238 Mon Sep 17 00:00:00 2001 From: Vitaliy Date: Tue, 18 Jun 2024 23:48:40 +0300 Subject: [PATCH] =?UTF-8?q?=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB=20=D0=B0?= =?UTF-8?q?=D0=B2=D1=82=D0=BE=D1=80=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8E=20?= =?UTF-8?q?=D0=B8=20=D1=80=D0=B5=D0=B3=D0=B5=D1=81=D1=82=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D1=8E.=20=D0=A0=D0=BE=D0=BB=D0=B8=20=D1=81=D0=BB=D0=BE?= =?UTF-8?q?=D0=BC=D0=B0=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 4 + .../DbHelpersEndpointsExtensions.cs | 82 +++++++++++++ .../Extensions/ServicesExtensions.cs | 16 +++ .../HackathonPreparing.ApiService.csproj | 4 +- .../HackathonPreparing.ApiService/Program.cs | 116 ++++++++---------- .../IdentityRoleEntityTypeConfiguration.cs | 20 +++ .../UserEntityTypeConfiguration.cs | 12 ++ .../User/EfCore/User.cs | 10 ++ .../User/EfCore/UserContext.cs | 19 +++ .../User/OpenApi/UserOpenApiSchemeFilter.cs | 33 +++++ .../User/UserController.cs | 9 ++ .../WeatherForecast/WeatherForecast.cs | 18 +++ .../WeatherForecastContext.cs} | 21 +--- .../WeatherForecastEndpointsExtensions.cs | 60 +++++++++ .../HackathonPreparing.AppHost/Program.cs | 21 +++- 15 files changed, 359 insertions(+), 86 deletions(-) create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Extensions/DbHelpersEndpointsExtensions.cs create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Extensions/ServicesExtensions.cs create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/EntityConfigurations/IdentityRoleEntityTypeConfiguration.cs create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/EntityConfigurations/UserEntityTypeConfiguration.cs create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/User.cs create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/UserContext.cs create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/OpenApi/UserOpenApiSchemeFilter.cs create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/UserController.cs create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecast.cs rename HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/{DatabaseContext.cs => WeatherForecast/WeatherForecastContext.cs} (69%) create mode 100644 HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecastEndpointsExtensions.cs diff --git a/.gitignore b/.gitignore index f3a3320..ed7bc38 100644 --- a/.gitignore +++ b/.gitignore @@ -47,6 +47,8 @@ bld/ [Ll]og/ [Ll]ogs/ +Migrations/ +VolumeMount.AppHost-postgresql-data/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot @@ -69,6 +71,8 @@ nunit-*.xml [Rr]eleasePS/ dlldata.c +VolumeMount.AppHost-postgresql-data/ + # Benchmark Results BenchmarkDotNet.Artifacts/ diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Extensions/DbHelpersEndpointsExtensions.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Extensions/DbHelpersEndpointsExtensions.cs new file mode 100644 index 0000000..8839ff1 --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Extensions/DbHelpersEndpointsExtensions.cs @@ -0,0 +1,82 @@ + +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Swashbuckle.AspNetCore.SwaggerGen; + +public static class DbHelpersEndpointsExtensions +{ + public static RouteGroupBuilder AddDbHelpersEndpoints(this WebApplication app) + { + var group = app.MapGroup("/db"); + + group.MapPost("/migrate/{contexClassName}", async (string contexClasstName, IServiceProvider services) => + { + var contextType = typeof(Program).Assembly.GetType(contexClasstName); + + if(contextType is null) + return Results.NotFound(); + + var inheritanceChain = contextType.GetInheritanceChain(); + + if(!inheritanceChain.Any(t => typeof(DbContext) == t)) + return Results.NotFound(); + + + using var scope = services.CreateScope(); + + var dbContext = (DbContext)scope.ServiceProvider.GetRequiredService(contextType); + + await dbContext.Database.MigrateAsync(); + return Results.Ok(); + }); + + group.MapPost("/initdb/{contexClassName}", async (string contexClasstName, IServiceProvider services) => + { + var contextType = typeof(Program).Assembly.GetType(contexClasstName); + + if(contextType is null) + return Results.NotFound(); + + var inheritanceChain = contextType.GetInheritanceChain(); + + if(!inheritanceChain.Any(t => typeof(DbContext) == t)) + return Results.NotFound(); + + + using var scope = services.CreateScope(); + + var dbContext = (DbContext)scope.ServiceProvider.GetRequiredService(contextType); + + await dbContext.Database.EnsureCreatedAsync(); + return Results.Ok(); + }); + + group.MapPost("/add-moderator", async ([FromServices]UserManager userManager) => { + var user = new User{ + Email = "m@gmail.com", + UserName = "m@gmail.com" + }; + var result = await userManager.CreateAsync(user, "PassPass123_"); + + if(!result.Succeeded) + return Results.BadRequest(result.Errors); + + var roleResult = await userManager.AddToRoleAsync(user, "moderator"); + + if(!roleResult.Succeeded) + return Results.BadRequest(roleResult.Errors); + + return Results.Ok(new { + Login = "m@gmail.com", + Password = "PassPass123_", + Role = "moderator" + }); + }).WithDescription($"Create user with login/email/username: m@gmail.com and password: PassPass123_"); + + group.WithTags("db"); + + return group; + } +} \ No newline at end of file diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Extensions/ServicesExtensions.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Extensions/ServicesExtensions.cs new file mode 100644 index 0000000..d424fa2 --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Extensions/ServicesExtensions.cs @@ -0,0 +1,16 @@ + + + + +using Microsoft.EntityFrameworkCore; + +public static class ServicesExtensions +{ + + public static void AddDbContextWithDefaultConfiguration(this WebApplicationBuilder builder) where TDbContext : DbContext + { + builder.AddNpgsqlDbContext("prod", null, + optionsBuilder => optionsBuilder.UseNpgsql(npgsqlBuilder => + npgsqlBuilder.MigrationsAssembly(typeof(Program).Assembly.GetName().Name))); + } +} \ No newline at end of file diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/HackathonPreparing.ApiService.csproj b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/HackathonPreparing.ApiService.csproj index 8dedc76..3645b3f 100644 --- a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/HackathonPreparing.ApiService.csproj +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/HackathonPreparing.ApiService.csproj @@ -7,11 +7,13 @@ - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Program.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Program.cs index b41f946..77db60c 100644 --- a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Program.cs +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/Program.cs @@ -1,5 +1,5 @@ using HackathonPreparing.ApiService; -using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Identity; using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); @@ -7,90 +7,78 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { - c.SwaggerDoc("v1", new OpenApiInfo { - Title = "Weather Forecast API", - Description = "Weather forecast API for the HackathonPreparing project.", - Version = "v1" }); + c.SchemaFilter(); + c.AddSecurityDefinition("AccessToken", new OpenApiSecurityScheme { + In = ParameterLocation.Header, + Description = "can get in /login or /register", + Name = "Authorization", + Type = SecuritySchemeType.Http, + BearerFormat = "JWT", + Scheme = "bearer" + }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement{ + { + new OpenApiSecurityScheme { + Reference = new OpenApiReference{ + Type = ReferenceType.SecurityScheme, + Id = "AccessToken" + } + }, + new string[]{} + } + }); }); // Add service defaults & Aspire components. -builder.AddServiceDefaults(); +//we dont need it now +//builder.AddServiceDefaults(); + + + +builder.Services.AddAuthorization(); + +builder.Services.AddAuthorizationBuilder() + .AddPolicy("moderator", policy => + policy.RequireRole("MODERATOR")); + +//TODO BEARER +builder.Services.AddAuthentication().AddBearerToken(IdentityConstants.BearerScheme); + +builder.Services.AddIdentity>() + .AddEntityFrameworkStores() + .AddApiEndpoints(); // Add services to the container. builder.Services.AddProblemDetails(); -builder.AddNpgsqlDbContext("prod", null, - optionsBuilder => optionsBuilder.UseNpgsql(npgsqlBuilder => - npgsqlBuilder.MigrationsAssembly(typeof(Program).Assembly.GetName().Name))); +builder.AddDbContextWithDefaultConfiguration(); +builder.AddDbContextWithDefaultConfiguration(); var app = builder.Build(); -var logger = app.Services.GetRequiredService>(); +app.UsePathBase(new PathString("/api")); if (app.Environment.IsDevelopment()) { + var logger = app.Services.GetRequiredService>(); logger.LogWarning("!!!!!!! Call /ensure-created enpoint or /migrate if no db !!!!!!!!"); app.UseSwagger(); - app.UseSwaggerUI(c => - { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "Weather Forecast API V1"); - }); - app.MapGet("/ensure-created", async (DatabaseContext db) => await db.Database.EnsureCreatedAsync()); - - app.MapGet("/migrate", async (DatabaseContext db) => await db.Database.MigrateAsync()); + app.UseSwaggerUI(); + app.AddDbHelpersEndpoints(); } // Configure the HTTP request pipeline. app.UseExceptionHandler(); +app.UseAuthorization(); +app.UseAuthentication(); -app.MapGet("/weatherforecast", async (DatabaseContext db) => await db.Forecasts.ToListAsync()); -app.MapDelete("/weatherforecast/{id}", async (DatabaseContext db, int id) => -{ - var forecast = await db.Forecasts.FindAsync(id); - if (forecast == null) - { - return Results.NotFound(); - } - - db.Forecasts.Remove(forecast); - await db.SaveChangesAsync(); - - return Results.NoContent(); -}); -app.MapPost("/weatherforecast", async (DatabaseContext db, WeatherForecast forecast) => -{ - db.Forecasts.Add(forecast); - await db.SaveChangesAsync(); - - return Results.Created($"/weatherforecast/{forecast.Id}", forecast); -}); -app.MapPut("/weatherforecast/{id}", async (DatabaseContext db, int id, WeatherForecast forecast) => -{ - if (id != forecast.Id) - { - return Results.BadRequest(); - } - - db.Entry(forecast).State = EntityState.Modified; - - try - { - await db.SaveChangesAsync(); - } - catch (DbUpdateConcurrencyException) - { - if (await db.Forecasts.FindAsync(id) == null) - { - return Results.NotFound(); - } - - throw; - } - - return Results.NoContent(); -}); - +app.AddWeatherForecastEndpoints(); app.MapDefaultEndpoints(); +app.MapGroup("/user") + .MapIdentityApi() + .WithTags("user"); + app.Run(); diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/EntityConfigurations/IdentityRoleEntityTypeConfiguration.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/EntityConfigurations/IdentityRoleEntityTypeConfiguration.cs new file mode 100644 index 0000000..816759f --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/EntityConfigurations/IdentityRoleEntityTypeConfiguration.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +public class IdentityRoleEntityTypeConfiguration : IEntityTypeConfiguration> +{ + public void Configure(EntityTypeBuilder> builder) + { + builder.HasData( + [ + new IdentityRole{ + Id = 1, + Name = "moderator", + NormalizedName = "MODERATOR", + ConcurrencyStamp = Guid.NewGuid().ToString() + } + ] + ); + } +} \ No newline at end of file diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/EntityConfigurations/UserEntityTypeConfiguration.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/EntityConfigurations/UserEntityTypeConfiguration.cs new file mode 100644 index 0000000..edb888c --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/EntityConfigurations/UserEntityTypeConfiguration.cs @@ -0,0 +1,12 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + + +//Example how add Fluent Building in project +public class UserEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + + } +} diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/User.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/User.cs new file mode 100644 index 0000000..038bf43 --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/User.cs @@ -0,0 +1,10 @@ + + +using Microsoft.AspNetCore.Identity; + +public class User : IdentityUser +{ + public string? AboutMe { get; set; } + + public override bool TwoFactorEnabled => false; +} \ No newline at end of file diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/UserContext.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/UserContext.cs new file mode 100644 index 0000000..ab3cf7b --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/EfCore/UserContext.cs @@ -0,0 +1,19 @@ + + +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; + +public class UserContext : IdentityDbContext, int> +{ + public UserContext (DbContextOptions options) : base(options) {} + + + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + builder.ApplyConfigurationsFromAssembly(typeof(Program).Assembly); + builder.HasDefaultSchema("user"); + } +} \ No newline at end of file diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/OpenApi/UserOpenApiSchemeFilter.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/OpenApi/UserOpenApiSchemeFilter.cs new file mode 100644 index 0000000..98a7a26 --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/OpenApi/UserOpenApiSchemeFilter.cs @@ -0,0 +1,33 @@ + + +using HackathonPreparing.ApiService.Migrations; +using Microsoft.AspNetCore.Identity.Data; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +public class UserOpenApiSchemeFilter : ISchemaFilter +{ + public void Apply(OpenApiSchema schema, SchemaFilterContext context) + { + if (context.Type == typeof(LoginRequest)) + { + schema.Example = new OpenApiObject() + { + ["email"] = new OpenApiString("email@gmail.com"), + ["password"] = new OpenApiString("PassPass123_"), + }; + } + + + + if (context.Type == typeof(RegisterRequest)) + { + schema.Example = new OpenApiObject() + { + ["email"] = new OpenApiString("email@gmail.com"), + ["password"] = new OpenApiString("PassPass123_"), + }; + } + } +} \ No newline at end of file diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/UserController.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/UserController.cs new file mode 100644 index 0000000..9d33baf --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/User/UserController.cs @@ -0,0 +1,9 @@ +using Microsoft.AspNetCore.Mvc; + +namespace HackathonPreparing.ApiService.User +{ + public class UserController : Controller + { + + } +} diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecast.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecast.cs new file mode 100644 index 0000000..5f1b846 --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecast.cs @@ -0,0 +1,18 @@ +namespace HackathonPreparing.ApiService; + +public class WeatherForecast +{ + public WeatherForecast(int id, DateOnly date, int temperatureC, string summary) + { + Id = id; + Date = date; + TemperatureC = temperatureC; + Summary = summary; + } + + + public int Id { get; set; } + public DateOnly Date { get; set; } + public int TemperatureC { get; set; } + public string Summary { get; set; } +} \ No newline at end of file diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/DatabaseContext.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecastContext.cs similarity index 69% rename from HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/DatabaseContext.cs rename to HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecastContext.cs index 706023e..73d4652 100644 --- a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/DatabaseContext.cs +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecastContext.cs @@ -2,9 +2,9 @@ using Microsoft.EntityFrameworkCore; namespace HackathonPreparing.ApiService; -public sealed class DatabaseContext : DbContext +public sealed class WeatherForecastContext : DbContext { - public DatabaseContext(DbContextOptions options) + public WeatherForecastContext(DbContextOptions options) : base(options) { @@ -39,20 +39,3 @@ public sealed class DatabaseContext : DbContext base.OnModelCreating(modelBuilder); } } - -public class WeatherForecast -{ - public WeatherForecast(int id, DateOnly date, int temperatureC, string summary) - { - Id = id; - Date = date; - TemperatureC = temperatureC; - Summary = summary; - } - - - public int Id { get; set; } - public DateOnly Date { get; set; } - public int TemperatureC { get; set; } - public string Summary { get; set; } -} \ No newline at end of file diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecastEndpointsExtensions.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecastEndpointsExtensions.cs new file mode 100644 index 0000000..d3fe79b --- /dev/null +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.ApiService/WeatherForecast/WeatherForecastEndpointsExtensions.cs @@ -0,0 +1,60 @@ + + + +using HackathonPreparing.ApiService; +using Microsoft.EntityFrameworkCore; + +public static class WeatherForecastExtensions +{ + public static void AddWeatherForecastEndpoints (this WebApplication app) + { + var group = app.MapGroup("/weatherforecast"); + group.MapGet("/", async (WeatherForecastContext db) => await db.Forecasts.ToListAsync()); + group.MapDelete("/{id}", async (WeatherForecastContext db, int id) => + { + var forecast = await db.Forecasts.FindAsync(id); + if (forecast == null) + { + return Results.NotFound(); + } + + db.Forecasts.Remove(forecast); + await db.SaveChangesAsync(); + + return Results.NoContent(); + }).RequireAuthorization("moderator"); + group.MapPost("/", async (WeatherForecastContext db, WeatherForecast forecast) => + { + db.Forecasts.Add(forecast); + await db.SaveChangesAsync(); + + return Results.Created($"/weatherforecast/{forecast.Id}", forecast); + }); + group.MapPut("/{id}", async (WeatherForecastContext db, int id, WeatherForecast forecast) => + { + if (id != forecast.Id) + { + return Results.BadRequest(); + } + + db.Entry(forecast).State = EntityState.Modified; + + try + { + await db.SaveChangesAsync(); + } + catch (DbUpdateConcurrencyException) + { + if (await db.Forecasts.FindAsync(id) == null) + { + return Results.NotFound(); + } + + throw; + } + + return Results.NoContent(); + }).RequireAuthorization("moderator"); + group.WithTags("weatherforecast"); + } +} \ No newline at end of file diff --git a/HackathonPreparing/HackathonPreparing/HackathonPreparing.AppHost/Program.cs b/HackathonPreparing/HackathonPreparing/HackathonPreparing.AppHost/Program.cs index 4191405..c7ea8f8 100644 --- a/HackathonPreparing/HackathonPreparing/HackathonPreparing.AppHost/Program.cs +++ b/HackathonPreparing/HackathonPreparing/HackathonPreparing.AppHost/Program.cs @@ -1,9 +1,26 @@ + var builder = DistributedApplication.CreateBuilder(args); +//use it +//dotnet user-secrets set Parameters:postgresql-password _StroNG_PaSSworD_ +//dotnet user-secrets set Parameters:postgresql-username dev_user + +//.WithBindMount("VolumeMount.AppHost-postgresql-data", "/var/lib/postgresql/data") + var cache = builder.AddRedis("cache"); -var postgres = builder.AddPostgres("postgres").WithPgAdmin(); -var postgresdb = postgres.AddDatabase("prod"); +var sqlPassword = builder.AddParameter("postgresql-password", secret: true); + +var sqlUser = builder.AddParameter("postgresql-username", secret: true); + +var postgresdb = builder + //.AddPostgres("postgres", password: sqlPassword, userName: sqlUser) + .AddPostgres("postgres") + .WithPgAdmin() + //.WithDataVolume() + .AddDatabase("prod"); + + var apiService = builder.AddProject("apiservice").WithReference(postgresdb); builder.AddProject("webfrontend")