fix(security): fix 5 P0 security blockers — SEC-C-01 through SEC-C-05

SEC-C-01: Replace Neon PostgreSQL credentials (npg_Ssfy6HKO0cXI) with local
dev connection strings in all 19 appsettings.json files. Production credentials
must be injected via ConnectionStrings__DefaultConnection env var. Add
appsettings.Production.json and appsettings.Staging.json to .gitignore.

SEC-C-02: Add services/goodgo-mcp-server/.env to root .gitignore. Create
.env.example with safe placeholder values documenting required variables.

SEC-C-03: Wrap AddDeveloperSigningCredential() in env check — development only.
Non-development environments must provide X.509 certificate via
IdentityServer:SigningCertificatePath and IdentityServer:SigningCertificatePassword.

SEC-C-04: Remove 4 unauthenticated debug endpoints from StaffController:
GET debug/all, POST debug/seed, POST debug/update-userid, POST debug/update-merchant.
These endpoints allowed privilege escalation and data exfiltration without auth.

SEC-C-05: Removed endpoints containing SQL injection via string interpolation
(lines 307, 367 in StaffController). Also removed [AllowAnonymous] from
GET lookup endpoint — inherits class-level [Authorize].

BREAKING: debug/* endpoints are permanently removed. BFF lookup endpoint now
requires authentication.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Ho Ngoc Hai
2026-03-23 09:47:07 +07:00
parent 6d0ca5bee5
commit 25f68781ad
23 changed files with 78 additions and 199 deletions

9
.gitignore vendored
View File

@@ -61,6 +61,15 @@ infra/secrets/**/*
!infra/secrets/**/.env.example
!infra/secrets/**/.gitignore
# .NET appsettings with environment-specific secrets (use env vars instead)
appsettings.Production.json
appsettings.Staging.json
appsettings.production.json
appsettings.staging.json
# MCP server secrets
services/goodgo-mcp-server/.env
# Temporary files
*.tmp
*.temp

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "postgresql://neondb_owner:npg_Ssfy6HKO0cXI@ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech/ads_analytics_service?sslmode=require&channel_binding=require"
"DefaultConnection": "Host=localhost;Database=ads_analytics_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "postgresql://neondb_owner:npg_Ssfy6HKO0cXI@ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech/ads_billing_service?sslmode=require&channel_binding=require"
"DefaultConnection": "Host=localhost;Database=ads_billing_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "postgresql://neondb_owner:npg_Ssfy6HKO0cXI@ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech/ads_manager_service?sslmode=require&channel_binding=require"
"DefaultConnection": "Host=localhost;Database=ads_manager_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "postgresql://neondb_owner:npg_Ssfy6HKO0cXI@ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech/ads_serving_service?sslmode=require&channel_binding=require"
"DefaultConnection": "Host=localhost;Database=ads_serving_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "postgresql://neondb_owner:npg_Ssfy6HKO0cXI@ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech/ads_tracking_service?sslmode=require&channel_binding=require"
"DefaultConnection": "Host=localhost;Database=ads_tracking_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Database=booking_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=booking_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Database=catalog_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=catalog_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Database=chat_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require",
"DefaultConnection": "Host=localhost;Database=chat_service;Username=goodgo;Password=goodgo-local-2024",
"Redis": "localhost:6379"
},
"SignalR": {
@@ -55,4 +55,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Database=fnb_engine;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=fnb_engine;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -1,12 +1,13 @@
# GoodGo MCP Server Configuration
# GoodGo MCP Server — Environment Variables
# Copy this file to .env and fill in actual values.
# NEVER commit .env to git.
# API Gateway URL (Traefik routes all services by path prefix)
# Docker local: http://localhost/api/v1 (port 80 via Traefik)
# Staging: https://api.staging.goodgo.vn/api/v1
# API Gateway
API_GATEWAY_URL=http://localhost/api/v1
# Default shop for convenience (Cobic Coffee)
DEFAULT_SHOP_ID=e1f392af-fe95-4c7f-8656-5b74ad5fd0a9
# Default shop for testing (replace with your merchant shop ID)
DEFAULT_SHOP_ID=
# JWT token (get from IAM login)
# JWT Bearer token for API authentication
# Obtain from IAM service: POST /api/v1/auth/token
API_TOKEN=

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Port=5432;Database=iam_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=iam_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"Host": "167.114.174.113",
@@ -77,4 +77,4 @@
"IssuerUri": "http://iam-service"
},
"AllowedHosts": "*"
}
}

View File

@@ -107,7 +107,7 @@ public static class DependencyInjection
// VI: Cấu hình Duende IdentityServer
var issuerUri = configuration["IdentityServer:IssuerUri"];
services.AddIdentityServer(options =>
var identityBuilder = services.AddIdentityServer(options =>
{
// EN: Set fixed issuer URI to ensure consistency across hosts and containers
// VI: Đặt issuer URI cố định để đảm bảo nhất quán giữa host và container
@@ -138,8 +138,28 @@ public static class DependencyInjection
.AddInMemoryApiResources(Config.ApiResources)
.AddInMemoryClients(Config.Clients)
.AddAspNetIdentity<ApplicationUser>()
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
.AddDeveloperSigningCredential(); // EN: Use certificate in production / VI: Dùng certificate trong production
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();
// EN: Signing credential — dev uses in-memory key, production MUST use a real X.509 certificate.
// VI: Signing credential — dev dùng key in-memory, production PHẢI dùng X.509 certificate thật.
if (environmentName == "Development" || string.IsNullOrEmpty(environmentName))
{
identityBuilder.AddDeveloperSigningCredential();
}
else
{
// EN: Read signing certificate path and password from environment variables.
// VI: Đọc đường dẫn và mật khẩu certificate từ biến môi trường.
var certPath = configuration["IdentityServer:SigningCertificatePath"]
?? throw new InvalidOperationException(
"IdentityServer:SigningCertificatePath must be set in non-Development environments. " +
"Provide a valid X.509 certificate via environment variable.");
var certPassword = configuration["IdentityServer:SigningCertificatePassword"]
?? throw new InvalidOperationException(
"IdentityServer:SigningCertificatePassword must be set in non-Development environments.");
var cert = new System.Security.Cryptography.X509Certificates.X509Certificate2(certPath, certPassword);
identityBuilder.AddSigningCredential(cert);
}
// EN: Add JWT Bearer authentication for API endpoints using local IdentityServer
// VI: Thêm JWT Bearer authentication cho API endpoints sử dụng IdentityServer cục bộ

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Database=inventory_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=inventory_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Port=5432;Database=membership_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=membership_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"Host": "167.114.174.113",
@@ -48,4 +48,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -219,162 +219,11 @@ public class StaffPublicController : ControllerBase
}
}
/// <summary>
/// EN: Debug endpoint to list all staff (dev only).
/// VI: Endpoint debug để list tất cả staff (dev only).
/// </summary>
[HttpGet("debug/all")]
[AllowAnonymous]
public async Task<IActionResult> DebugAllStaff()
{
var ctx = HttpContext.RequestServices.GetRequiredService<MerchantService.Infrastructure.MerchantServiceContext>();
var staffCount = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.CountAsync(ctx.MerchantStaff);
var merchantCount = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.CountAsync(ctx.Merchants);
var merchants = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync(
System.Linq.Queryable.Take(ctx.Merchants, 5));
var staffItems = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync(
System.Linq.Queryable.Take(ctx.MerchantStaff, 20));
return Ok(new
{
staffCount, merchantCount,
merchants = merchants.Select(m => new { m.Id, m.BusinessName, m.StatusId }),
staff = staffItems.Select(s => new { s.Id, s.Email, s.FirstName, s.LastName, s.UserId, s.MerchantId, statusId = s.StatusId })
});
}
/// <summary>
/// EN: Debug seed endpoint — seed test staff data (dev only).
/// VI: Debug seed — tạo dữ liệu test staff (dev only).
/// </summary>
[HttpPost("debug/seed")]
[AllowAnonymous]
public async Task<IActionResult> DebugSeedStaff()
{
var staffRepo = HttpContext.RequestServices.GetRequiredService<MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.IMerchantStaffRepository>();
var ctx = HttpContext.RequestServices.GetRequiredService<MerchantService.Infrastructure.MerchantServiceContext>();
// Get first merchant
var merchant = await Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.FirstOrDefaultAsync(ctx.Merchants);
if (merchant == null) return BadRequest(new { message = "No merchant found" });
var staffData = new[]
{
new { Email = "tranvanb@goodgo.vn", FirstName = "Bình", LastName = "Trần Văn", Role = "Cashier", UserId = Guid.Parse("9160b2f3-619b-48de-aade-8098cef2a426") },
new { Email = "tranvanc@goodgo.vn", FirstName = "Cường", LastName = "Trần Văn", Role = "Waiter", UserId = Guid.NewGuid() },
new { Email = "tranvand@goodgo.vn", FirstName = "Dũng", LastName = "Trần Văn", Role = "Kitchen", UserId = Guid.NewGuid() },
new { Email = "tranvane@goodgo.vn", FirstName = "Huy", LastName = "Trần Văn", Role = "Manager", UserId = Guid.NewGuid() },
};
var created = new List<object>();
foreach (var sd in staffData)
{
var existing = await staffRepo.GetByEmailAsync(sd.Email);
if (existing != null) { created.Add(new { sd.Email, status = "already_exists", existing.Id }); continue; }
var role = sd.Role switch
{
"Cashier" => MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.StaffRole.Cashier,
"Waiter" => MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.StaffRole.Waiter,
"Kitchen" => MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.StaffRole.Kitchen,
"Manager" => MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.StaffRole.Manager,
_ => MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.StaffRole.Cashier,
};
var staff = MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.MerchantStaff.CreateActive(
merchant.Id, sd.UserId, sd.Email, role, firstName: sd.FirstName, lastName: sd.LastName);
staffRepo.Add(staff);
created.Add(new { sd.Email, status = "created", staff.Id });
}
await staffRepo.UnitOfWork.SaveEntitiesAsync();
// Also seed a shop if none exists and assign staff to it
Guid? shopId = null;
try
{
var shopIdResult = await ctx.Database.ExecuteSqlRawAsync(@"
INSERT INTO shops (id, merchant_id, name, slug, type_id, category_id, status_id, created_at)
SELECT @p0, @p1, 'Cobic Coffee', 'cobic-coffee', 1, 1, 2, NOW()
WHERE NOT EXISTS (SELECT 1 FROM shops WHERE merchant_id = @p1)
", Guid.Parse("e1f392af-fe95-4c7f-8656-5b74ad5fd0a9"), merchant.Id);
// Find shop for this merchant via raw connection
Guid existingShopId = Guid.Empty;
var conn = ctx.Database.GetDbConnection();
if (conn.State != System.Data.ConnectionState.Open) await conn.OpenAsync();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = $"SELECT id FROM shops WHERE merchant_id = '{merchant.Id}' LIMIT 1";
var result = await cmd.ExecuteScalarAsync();
if (result != null) existingShopId = Guid.Parse(result.ToString()!);
}
if (existingShopId != Guid.Empty)
{
shopId = existingShopId;
// Assign all created staff to this shop
foreach (var sd in staffData)
{
var staffEntity = await staffRepo.GetByEmailAsync(sd.Email);
if (staffEntity != null && !staffEntity.ShopAssignments.Any())
{
staffEntity.AssignToShop(existingShopId, MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.ShopRole.Cashier);
staffRepo.Update(staffEntity);
}
}
await staffRepo.UnitOfWork.SaveEntitiesAsync();
}
}
catch (Exception ex)
{
// Shop creation may fail if columns don't exist — that's OK, leave request can still work
_logger.LogWarning("Shop seed failed: {Error}", ex.Message);
}
return Ok(new { merchantId = merchant.Id, shopId, created });
}
/// <summary>
/// EN: Debug update staff userId (dev only).
/// </summary>
[HttpPost("debug/update-userid")]
[AllowAnonymous]
public async Task<IActionResult> DebugUpdateStaffUserId([FromQuery] string email, [FromQuery] Guid userId)
{
var staffRepo = HttpContext.RequestServices.GetRequiredService<MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.IMerchantStaffRepository>();
var staff = await staffRepo.GetByEmailAsync(email);
if (staff == null) return NotFound(new { message = "Staff not found" });
// Use reflection to set private _userId field
var field = typeof(MerchantService.Domain.AggregatesModel.MerchantStaffAggregate.MerchantStaff)
.GetField("_userId", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
field?.SetValue(staff, userId);
staffRepo.Update(staff);
await staffRepo.UnitOfWork.SaveEntitiesAsync();
return Ok(new { success = true, staffId = staff.Id, userId, email });
}
/// <summary>
/// EN: Debug update merchant userId (dev only).
/// </summary>
[HttpPost("debug/update-merchant")]
[AllowAnonymous]
public async Task<IActionResult> DebugUpdateMerchantUserId([FromQuery] Guid merchantId, [FromQuery] Guid userId)
{
var ctx = HttpContext.RequestServices.GetRequiredService<MerchantService.Infrastructure.MerchantServiceContext>();
var conn = ctx.Database.GetDbConnection();
if (conn.State != System.Data.ConnectionState.Open) await conn.OpenAsync();
using var cmd = conn.CreateCommand();
cmd.CommandText = $"UPDATE merchants SET user_id = '{userId}' WHERE id = '{merchantId}'";
var rows = await cmd.ExecuteNonQueryAsync();
return Ok(new { success = rows > 0, merchantId, userId, rowsAffected = rows });
}
/// <summary>
/// EN: Lookup staff profile by email — used by BFF to resolve staff identity.
/// VI: Tìm staff profile theo email — BFF dùng để resolve staff identity.
/// </summary>
[HttpGet("lookup")]
[AllowAnonymous]
public async Task<IActionResult> LookupByEmail([FromQuery] string email)
{
if (string.IsNullOrEmpty(email))

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Database=merchant_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=merchant_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -41,4 +41,4 @@
"RequireHttpsMetadata": false
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Port=5432;Database=mining_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=mining_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Database=order_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=order_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -57,4 +57,4 @@
"WalletService": "http://wallet-service-net:8080"
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Port=5432;Database=promotion_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=promotion_service;Username=goodgo;Password=goodgo-local-2024"
},
"WalletService": {
"BaseUrl": "http://wallet-service-net:8080",
@@ -60,4 +60,4 @@
"ConnectionString": "redis:6379"
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Port=5432;Database=social_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=social_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Port=5432;Database=storage_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=storage_service;Username=goodgo;Password=goodgo-local-2024"
},
"Storage": {
"Provider": "minio",
@@ -75,4 +75,4 @@
"DefaultCacheTtlSeconds": 86400
},
"AllowedHosts": "*"
}
}

View File

@@ -30,7 +30,7 @@
]
},
"ConnectionStrings": {
"DefaultConnection": "Host=ep-holy-glitter-a4hongg7-pooler.us-east-1.aws.neon.tech;Database=wallet_service;Username=neondb_owner;Password=npg_Ssfy6HKO0cXI;SSL Mode=Require"
"DefaultConnection": "Host=localhost;Database=wallet_service;Username=goodgo;Password=goodgo-local-2024"
},
"Redis": {
"ConnectionString": "localhost:6379"
@@ -43,4 +43,4 @@
"RefreshTokenExpiryDays": 7
},
"AllowedHosts": "*"
}
}