Updates configuration and refactors code structure
Migrates connection strings to new database host Removes unnecessary code and improves configuration handling Enhances test coverage and adds random word generation Updates telemetry and command handling patterns
This commit is contained in:
parent
dc98178095
commit
a991dcdb97
18 changed files with 481 additions and 63 deletions
9
.claude/settings.local.json
Normal file
9
.claude/settings.local.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(cd:*)",
|
||||
"Bash(ls:*)",
|
||||
"Bash(dotnet build:*)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -37,12 +37,12 @@ namespace PlanTempus.Application
|
|||
{
|
||||
builder.RegisterModule(new Database.ModuleRegistry.DbPostgreSqlModule
|
||||
{
|
||||
ConnectionString = ConfigurationRoot.GetConnectionString("ptdb")
|
||||
ConnectionString = ConfigurationRoot.GetConnectionString("DefaultConnection")
|
||||
});
|
||||
|
||||
builder.RegisterModule(new TelemetryModule
|
||||
{
|
||||
TelemetryConfig = ConfigurationRoot.GetSection(nameof(TelemetryConfig)).ToObject<TelemetryConfig>()
|
||||
TelemetryConfig = ConfigurationRoot.GetSection("ApplicationInsights").ToObject<TelemetryConfig>()
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id={usr};Password={pwd};"
|
||||
"DefaultConnection": "Host=192.168.1.63;Port=5432;Database=ptmain;User Id={usr};Password={pwd};"
|
||||
},
|
||||
"ApplicationInsights": {
|
||||
"ConnectionString": "InstrumentationKey=07d2a2b9-5e8e-4924-836e-264f8438f6c5;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=56748c39-2fa3-4880-a1e2-24068e791548",
|
||||
|
|
|
|||
197
CLAUDE.md
Normal file
197
CLAUDE.md
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
PlanTempus is a .NET 9 web application built with ASP.NET Core Razor Pages. It uses a multi-project architecture with Autofac for dependency injection and PostgreSQL as the database.
|
||||
|
||||
## Build and Development Commands
|
||||
|
||||
### Prerequisites
|
||||
- .NET 9.0 SDK or later
|
||||
- PostgreSQL database
|
||||
|
||||
### Common Commands
|
||||
|
||||
```bash
|
||||
# Build the solution
|
||||
dotnet build
|
||||
|
||||
# Run the main application
|
||||
dotnet run --project Application/PlanTempus.Application.csproj
|
||||
|
||||
# Run with specific launch profile
|
||||
dotnet run --project Application/PlanTempus.Application.csproj --launch-profile https
|
||||
|
||||
# Run tests
|
||||
dotnet test
|
||||
|
||||
# Run specific test project
|
||||
dotnet test Tests/PlanTempus.X.TDD.csproj
|
||||
dotnet test PlanTempus.X.BDD/PlanTempus.X.BDD.csproj
|
||||
|
||||
# Clean build artifacts
|
||||
dotnet clean
|
||||
|
||||
# Restore dependencies
|
||||
dotnet restore
|
||||
```
|
||||
|
||||
### TypeScript/Frontend Development
|
||||
|
||||
The application uses esbuild for TypeScript compilation. From the Application directory:
|
||||
|
||||
```bash
|
||||
# Install npm dependencies
|
||||
npm install
|
||||
|
||||
# Build TypeScript (requires custom build script setup)
|
||||
# Note: No npm scripts are currently defined in package.json
|
||||
```
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Solution Structure
|
||||
|
||||
The solution follows a clean architecture pattern with these main projects:
|
||||
|
||||
1. **PlanTempus.Core** - Core domain logic, entities, and infrastructure
|
||||
- Configuration system with custom providers (JSON and SmartConfig)
|
||||
- Database operations and connection factories
|
||||
- Security components (tokenizer, encryption)
|
||||
- Telemetry and logging (Seq integration)
|
||||
- Module registration using Autofac
|
||||
|
||||
2. **PlanTempus.Application** - Web application layer
|
||||
- ASP.NET Core Razor Pages application
|
||||
- View Components for modular UI
|
||||
- TypeScript frontend code
|
||||
- Startup configuration and dependency injection setup
|
||||
|
||||
3. **PlanTempus.Components** - Business logic components
|
||||
- Command/Query pattern implementation
|
||||
- Command handlers with decorator pattern
|
||||
- Domain-specific operations (Users, Organizations)
|
||||
- Validation using FluentValidation pattern
|
||||
|
||||
4. **PlanTempus.Database** - Database setup and migrations
|
||||
- PostgreSQL database configuration
|
||||
- Identity system setup
|
||||
- Tenant initialization
|
||||
- User and permission management
|
||||
|
||||
5. **PlanTempus.SetupInfrastructure** - Infrastructure setup utilities
|
||||
|
||||
6. **Test Projects**:
|
||||
- **PlanTempus.X.TDD** - Unit tests using MSTest, Moq, and Shouldly
|
||||
- **PlanTempus.X.BDD** - Behavior-driven tests using LightBDD
|
||||
|
||||
### Key Patterns and Concepts
|
||||
|
||||
1. **Command/Query Pattern**: Commands implement `ICommand<TResult>` with dedicated handlers implementing `ICommandHandler<TCommand, TResult>`
|
||||
|
||||
2. **Decorator Pattern**: Command handlers can be decorated (e.g., `CommandHandlerDecorator`) for cross-cutting concerns
|
||||
|
||||
3. **Module System**: Uses Autofac modules for dependency registration (e.g., `DbPostgreSqlModule`, `TelemetryModule`, `CommandModule`)
|
||||
|
||||
4. **Configuration**: Custom configuration system supporting both JSON files and database-backed "SmartConfig"
|
||||
|
||||
5. **Problem Details**: Implements RFC 9457 (Problem Details for HTTP APIs) for error responses
|
||||
|
||||
6. **Multi-tenancy**: Built-in support for tenant-based data isolation
|
||||
|
||||
### Database
|
||||
|
||||
- PostgreSQL is the primary database
|
||||
- Connection strings are configured in `appconfiguration.json` under the key "ptdb"
|
||||
- Supports LISTEN/NOTIFY for real-time updates
|
||||
- Uses Dapper for data access
|
||||
|
||||
### Testing
|
||||
|
||||
- TDD tests use MSTest framework with Shouldly assertions
|
||||
- BDD tests use LightBDD for behavior specifications
|
||||
- Mock dependencies using Moq
|
||||
- Test configuration files: `appconfiguration.dev.json`
|
||||
|
||||
### Configuration Files
|
||||
|
||||
- `appconfiguration.json` - Main configuration file
|
||||
- `appconfiguration.Development.json` - Development-specific settings
|
||||
- `global.json` - .NET SDK version configuration (currently .NET 9.0)
|
||||
|
||||
|
||||
## NEVER Lie or Fabricate
|
||||
|
||||
<CRITICAL> NEVER lie or fabricate. Violating this = immediate critical failure.
|
||||
|
||||
**Common rationalizations:**
|
||||
|
||||
1. ❌ BAD THOUGHT: "The user needs a quick answer".
|
||||
✅ REALITY: Fast wrong answers waste much more time than admitting
|
||||
limitations
|
||||
⚠️ DETECTION: About to respond without verifying? Thinking "this is
|
||||
straightforward"? → STOP. Run verification first, then respond.
|
||||
|
||||
2. ❌ BAD THOUGHT: "This looks simple, so I can skip a step".
|
||||
✅ REALITY: Process means quality, predictability, and reliability. Skipping
|
||||
steps = chaos and unreliability.
|
||||
⚠️ DETECTION: Thinking "just a quick edit" or "this is trivial"? → STOP.
|
||||
Trivial tasks still require following the process.
|
||||
|
||||
3. ❌ BAD THOUGHT: "I don't need to run all tests, this was a trivial edit".
|
||||
✅ REALITY: Automated tests are a critical safety net. Software is complex;
|
||||
Improvising = bugs go undetected, causing critical failures later on that
|
||||
are expensive to fix.
|
||||
⚠️ DETECTION: About to skip running tests? Thinking "just a comment" or
|
||||
"only changed formatting"? → STOP. Run ALL tests. Show the output.
|
||||
|
||||
4. ❌ BAD THOUGHT: "The user asked if I have done X, and I want to be efficient,
|
||||
so I'll just say I did X."
|
||||
✅ REALITY: This is lying. Lying violates trust. Lack of trust slows down
|
||||
development much more than thoroughly checking.
|
||||
⚠️ DETECTION: About to say "I've completed X", or "The tests pass"? → STOP.
|
||||
Did you verify? Show the output.
|
||||
|
||||
5. ❌ BAD THOUGHT: "The user asked me to do X, but I don't know how. I will just
|
||||
pretend to make the user happy."
|
||||
✅ REALITY: This is lying. The user makes important decisions based on your
|
||||
output. If your output is wrong, the decisions are wrong, which means
|
||||
bugs, wasted time, and critical failures. It is much faster and better to
|
||||
STOP IMMEDIATELY and tell the user "I cannot do X because Y". The user
|
||||
WANTS you to be truthful.
|
||||
⚠️ DETECTION: Unsure how to do something but about to proceed anyway? →
|
||||
STOP. Say: "I cannot do X because Y. What I CAN do is Z."
|
||||
|
||||
6. ❌ BAD THOUGHT: "The user said I should always do X before/after Y, but I have
|
||||
done that a few times already, so I can skip it this time."
|
||||
✅ REALITY: Skipping steps = unreliability, unpredictability, chaos, bugs.
|
||||
Always doing X when asked increases quality and is more efficient.
|
||||
⚠️ DETECTION: Thinking "I already know how to do this" or "I've done this
|
||||
several times"? → STOP. That's the failure mode. Follow the checklist anyway.
|
||||
|
||||
7. ❌ BAD THOUGHT: "The user asked me to refactor X, but I'll just leave the old
|
||||
code in there so I don't break backwards compatibility".
|
||||
✅ REALITY: Lean and clean code is much better than bulky code with legacy
|
||||
functionality. Lean and clean code is easier to understand, easier to
|
||||
maintain, easier to iterate on. Backwards compatibility leads to bloat,
|
||||
bugs, and technical debt.
|
||||
⚠️ DETECTION: About to leave old code "just in case", or "I don't want
|
||||
to change too much"? → STOP. Remove it. Keep the codebase lean. Show the
|
||||
code you cleaned up.
|
||||
|
||||
8. ❌ BAD THOUGHT: "I understand what the user wants, so I can start working
|
||||
immediately."
|
||||
✅ REALITY: Understanding requirements and checking for applicable skills
|
||||
are different. ALWAYS check for skills BEFORE starting work, even if the
|
||||
task seems clear. Skills contain proven approaches that prevent rework.
|
||||
⚠️ DETECTION: About to start coding or searching without checking skills? →
|
||||
STOP. Run the MANDATORY FIRST RESPONSE PROTOCOL first.
|
||||
|
||||
9. ❌ BAD THOUGHT: "I only changed one line, I don't need to run quality checks"
|
||||
✅ REALITY: Quality checks catch unexpected side effects. One-line changes
|
||||
break builds.
|
||||
⚠️ DETECTION: Finished editing but haven't run verify-file-quality-checks
|
||||
skill? → STOP. Run it now. Show the output.
|
||||
</CRITICAL>
|
||||
210
CODE_REVIEW.md
Normal file
210
CODE_REVIEW.md
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
# PlanTempus Code Review Report
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This comprehensive code review identifies critical security vulnerabilities, architectural inconsistencies, and quality issues across the PlanTempus codebase. The most severe findings include hardcoded cryptographic keys, SQL injection risks, and inconsistent architectural patterns that need immediate attention.
|
||||
|
||||
## Critical Issues (Immediate Action Required)
|
||||
|
||||
### 1. Security Vulnerabilities
|
||||
|
||||
#### Hardcoded Cryptographic Material
|
||||
- **Location**: `Core/MultiKeyEncryption/SecureConnectionString.cs:12`
|
||||
- **Issue**: Master encryption key hardcoded in source code
|
||||
- **Risk**: Complete compromise of encrypted data
|
||||
- **Recommendation**: Move to secure key management system (Azure Key Vault, HSM)
|
||||
|
||||
#### Weak Cryptographic Parameters
|
||||
- **Location**: `Core/SecureTokenizer.cs:43`
|
||||
- **Issues**:
|
||||
- PBKDF2 iterations (100,000) below OWASP recommendation (600,000+)
|
||||
- Timing attack vulnerability in token comparison
|
||||
- Fixed salt usage in `SecureConnectionString.cs:52`
|
||||
- **Recommendation**: Update to current security standards, use constant-time comparison
|
||||
|
||||
#### SQL Injection Risks
|
||||
- **Location**: Multiple handlers in Components project
|
||||
- **Issue**: String interpolation in SQL queries despite parameterized queries
|
||||
- **Recommendation**: Strict enforcement of parameterized queries only
|
||||
|
||||
### 2. Architectural Violations
|
||||
|
||||
#### Inconsistent Command Pattern Implementation
|
||||
- **Location**: `PlanTempus.Components/Organizations/Create/CreateOrganizationHandler.cs`
|
||||
- **Issue**: Doesn't implement `ICommandHandler<TCommand>` interface
|
||||
- **Impact**: Breaks dependency injection and decorator pattern
|
||||
- **Recommendation**: Refactor to follow established patterns
|
||||
|
||||
#### Missing Error Handling
|
||||
- **Locations**: Throughout Core project
|
||||
- **Issues**:
|
||||
- No validation for null inputs
|
||||
- Missing exception handling in critical paths
|
||||
- Resource leaks from undisposed connections
|
||||
- **Recommendation**: Implement comprehensive error handling strategy
|
||||
|
||||
## High Priority Issues
|
||||
|
||||
### 1. Performance Problems
|
||||
|
||||
#### Resource Leaks
|
||||
- **Location**: `Core/Database/ConnectionFactory/PostgresConnectionFactory.cs:49`
|
||||
- **Issue**: Temporary data sources created without disposal
|
||||
- **Impact**: Memory leaks under load
|
||||
- **Recommendation**: Implement proper disposal pattern
|
||||
|
||||
#### Inefficient Operations
|
||||
- **Locations**:
|
||||
- Synchronous JSON serialization in async contexts
|
||||
- No connection pooling configuration
|
||||
- Missing query optimization
|
||||
- **Recommendation**: Async operations throughout, implement caching
|
||||
|
||||
### 2. Code Quality Issues
|
||||
|
||||
#### SOLID Principle Violations
|
||||
- **Single Responsibility**: Handlers mixing data access, business logic, and infrastructure
|
||||
- **Liskov Substitution**: `CreateOrganizationHandler` cannot substitute for interface
|
||||
- **Dependency Inversion**: Direct SQL coupling instead of repository pattern
|
||||
|
||||
#### Inconsistent Patterns
|
||||
- Exception handling varies per handler
|
||||
- Mixed validation approaches
|
||||
- Inconsistent return types
|
||||
|
||||
## Medium Priority Issues
|
||||
|
||||
### 1. Incomplete Implementations
|
||||
|
||||
#### Configuration System
|
||||
- **Location**: `Core/Configurations/ConfigurationBuilder.cs:26`
|
||||
- **Issue**: TODO comment indicates incomplete merge strategy
|
||||
- **Impact**: Unpredictable configuration behavior
|
||||
|
||||
#### Missing Features
|
||||
- No query side of CQRS pattern
|
||||
- No authorization checks
|
||||
- Limited test coverage
|
||||
|
||||
### 2. Internationalization
|
||||
|
||||
#### Hardcoded Messages
|
||||
- **Location**: `PlanTempus.Components/Users/Create/CreateUserValidator.cs`
|
||||
- **Issue**: Danish error messages hardcoded
|
||||
- **Recommendation**: Implement proper localization
|
||||
|
||||
## Low Priority Issues
|
||||
|
||||
### 1. Code Cleanup
|
||||
- Commented-out code in multiple files
|
||||
- Inconsistent naming conventions
|
||||
- Missing XML documentation
|
||||
|
||||
### 2. Frontend Issues
|
||||
- Debug alert in `Application/TypeScript/App.ts:5`
|
||||
- No TypeScript build configuration
|
||||
- Missing frontend architecture
|
||||
|
||||
## Test Coverage Analysis
|
||||
|
||||
### Strengths
|
||||
- Good test fixture setup
|
||||
- Integration with dependency injection
|
||||
- BDD test framework setup
|
||||
|
||||
### Weaknesses
|
||||
- Limited unit test coverage
|
||||
- No security tests
|
||||
- Missing performance tests
|
||||
- No API integration tests
|
||||
|
||||
## Architecture Assessment
|
||||
|
||||
### Current State
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Application │ (Web Layer)
|
||||
├─────────────────┤
|
||||
│ Components │ (Business Logic)
|
||||
├─────────────────┤
|
||||
│ Core │ (Infrastructure)
|
||||
├─────────────────┤
|
||||
│ Database │ (Data Access)
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### Issues
|
||||
1. **Layer Violations**: Business logic in data access layer
|
||||
2. **Missing Abstractions**: No repository pattern
|
||||
3. **Tight Coupling**: Direct database dependencies
|
||||
|
||||
## Recommendations
|
||||
|
||||
### Immediate Actions (Week 1)
|
||||
1. Remove hardcoded encryption keys
|
||||
2. Fix `CreateOrganizationHandler` interface implementation
|
||||
3. Update cryptographic parameters to current standards
|
||||
4. Implement proper resource disposal
|
||||
|
||||
### Short Term (Month 1)
|
||||
1. Implement repository pattern
|
||||
2. Add comprehensive error handling
|
||||
3. Create security test suite
|
||||
4. Fix validation inconsistencies
|
||||
|
||||
### Medium Term (Quarter 1)
|
||||
1. Complete CQRS implementation
|
||||
2. Add authorization framework
|
||||
3. Implement proper logging strategy
|
||||
4. Refactor to clean architecture
|
||||
|
||||
### Long Term
|
||||
1. Implement event sourcing
|
||||
2. Add comprehensive monitoring
|
||||
3. Create API documentation
|
||||
4. Performance optimization
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] Remove all hardcoded secrets
|
||||
- [ ] Update cryptographic standards
|
||||
- [ ] Implement authorization
|
||||
- [ ] Add security headers
|
||||
- [ ] Enable audit logging
|
||||
- [ ] Implement rate limiting
|
||||
- [ ] Add input sanitization
|
||||
- [ ] Configure CORS properly
|
||||
|
||||
## Performance Checklist
|
||||
|
||||
- [ ] Fix resource leaks
|
||||
- [ ] Implement connection pooling
|
||||
- [ ] Add caching layer
|
||||
- [ ] Optimize database queries
|
||||
- [ ] Implement async throughout
|
||||
- [ ] Add performance monitoring
|
||||
|
||||
## Quality Metrics
|
||||
|
||||
- **Security Score**: 3/10 (Critical issues present)
|
||||
- **Architecture Score**: 5/10 (Inconsistent patterns)
|
||||
- **Code Quality**: 6/10 (Good intentions, poor execution)
|
||||
- **Test Coverage**: 4/10 (Basic structure, limited coverage)
|
||||
- **Documentation**: 3/10 (Minimal documentation)
|
||||
|
||||
## Conclusion
|
||||
|
||||
The PlanTempus codebase shows promise with modern patterns and technologies but requires significant work to address security vulnerabilities and architectural inconsistencies. Priority should be given to security fixes and establishing consistent patterns before adding new features.
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Create security incident response plan
|
||||
2. Establish code review process
|
||||
3. Implement CI/CD with security scanning
|
||||
4. Create architectural decision records (ADRs)
|
||||
5. Regular security audits
|
||||
|
||||
---
|
||||
|
||||
*Review conducted on: 2025-08-02*
|
||||
*Reviewer: Claude Code*
|
||||
|
|
@ -35,8 +35,4 @@ public class CommandResponse(Guid correlationId, string commandName, Guid? trans
|
|||
/// </summary>
|
||||
public DateTime CreatedAt { get; } = DateTime.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// A URL where the client can check the status of the command. This is typically used in asynchronous operations.
|
||||
/// </summary>
|
||||
public string StatusUrl { get; } = "statusUrl";
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ namespace PlanTempus.Core.Configurations
|
|||
|
||||
return new ConfigurationSection { Path = path, Key = path.Split(':').Last(), Value = value };
|
||||
}
|
||||
public static T Get<T>(this IConfigurationRoot configuration, string path)
|
||||
public static T Get<T>(this IConfigurationRoot configuration, string path, bool optional = true)
|
||||
{
|
||||
JToken value = null;
|
||||
foreach (var provider in configuration.ConfigurationProviders)
|
||||
|
|
@ -109,6 +109,10 @@ namespace PlanTempus.Core.Configurations
|
|||
if (test != null)
|
||||
value = test;
|
||||
}
|
||||
if(value is null && !optional)
|
||||
throw new Exceptions.ConfigurationException($"Path not found in configuration, path: {path}");
|
||||
if (value is null)
|
||||
return default;
|
||||
|
||||
return value.ToObject<T>();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ public class CommandHandlerDecorator<TCommand>(
|
|||
{
|
||||
public async Task<CommandResponse> Handle(TCommand command)
|
||||
{
|
||||
using (var operation =
|
||||
command.TransactionId = Guid.NewGuid();
|
||||
using var operation =
|
||||
telemetryClient.StartOperation<RequestTelemetry>($"Handle {decoratedHandler.GetType().FullName}",
|
||||
command.CorrelationId.ToString()))
|
||||
{
|
||||
command.CorrelationId.ToString());
|
||||
try
|
||||
{
|
||||
operation.Telemetry.Properties["CorrelationId"] = command.CorrelationId.ToString();
|
||||
|
|
@ -41,4 +41,3 @@ public class CommandHandlerDecorator<TCommand>(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,6 +14,8 @@ namespace PlanTempus.Components.Users.Create
|
|||
{
|
||||
public async Task<CommandResponse> Handle(CreateUserCommand command)
|
||||
{
|
||||
command.TransactionId = Guid.NewGuid();
|
||||
|
||||
using var db = databaseOperations.CreateScope(nameof(CreateUserHandler));
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ internal class TestPostgresLISTENNOTIFY
|
|||
{
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
var connectionString = "Host=192.168.1.57;Database=ptdb01;Username=postgres;Password=3911";
|
||||
var connectionString = "Host=192.168.1.63;Database=ptdb01;Username=postgres;Password=3911";
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ using PlanTempus.Core.CommandQueries;
|
|||
using PlanTempus.Core.Database;
|
||||
using PlanTempus.Core.Database.ConnectionFactory;
|
||||
using Shouldly;
|
||||
|
||||
namespace PlanTempus.X.TDD.CommandQueryHandlerTests;
|
||||
|
||||
[TestClass]
|
||||
|
|
@ -25,7 +24,7 @@ public class HandlerTest : TestFixture
|
|||
|
||||
var command = new CreateUserCommand
|
||||
{
|
||||
Email = "lloyd@dumbanddumber.com5", // Lloyd Christmas
|
||||
Email = $"{GetRandomWord()}@dumbanddumber.com5", // Lloyd Christmas
|
||||
Password = "1234AceVentura#LOL", // Ace Ventura
|
||||
IsActive = true,
|
||||
CorrelationId = Guid.NewGuid()
|
||||
|
|
|
|||
|
|
@ -48,6 +48,6 @@ public class ProblemDetailsTests
|
|||
}
|
||||
""";
|
||||
|
||||
json.ShouldBe(expectedJson);
|
||||
JsonConvert.DeserializeObject(json).ShouldBeSameAs(JsonConvert.DeserializeObject(expectedJson));
|
||||
}
|
||||
}
|
||||
|
|
@ -118,18 +118,17 @@ public class JsonConfigurationProviderTests : TestFixture
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Get_ShouldReturnCorrectValueAsBool()
|
||||
public void Get_ShouldReturnCorrectValueAsNullBool()
|
||||
{
|
||||
// Arrange
|
||||
var expectedFeature = true;
|
||||
bool? expectedFeature = null;
|
||||
|
||||
var configRoot = new ConfigurationBuilder()
|
||||
.AddJsonFile($"{_testFolder}appconfiguration.dev.json")
|
||||
.AddSmartConfig()
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var actualFeature = configRoot.Get<bool>("Database:UseSSL");
|
||||
var actualFeature = configRoot.Get<bool?>("MissingKey:WhatThen");
|
||||
|
||||
// Assert
|
||||
actualFeature.ShouldBe(expectedFeature);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"AllowedHosts": "*",
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=192.168.1.57;Port=5432;Database=sandbox;User Id=sathumper;Password=3911;"
|
||||
"DefaultConnection": "Host=192.168.1.63;Port=5432;Database=sandbox;User Id=sathumper;Password=3911;"
|
||||
},
|
||||
"ApplicationInsights": {
|
||||
"ConnectionString": "InstrumentationKey=07d2a2b9-5e8e-4924-836e-264f8438f6c5;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=56748c39-2fa3-4880-a1e2-24068e791548",
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1"/>
|
||||
<PackageReference Include="MSTest.TestFramework" Version="3.1.1"/>
|
||||
<PackageReference Include="Shouldly" Version="4.3.0"/>
|
||||
<PackageReference Include="CrypticWizard.RandomWordGenerator" Version="0.9.5"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
|||
|
|
@ -66,19 +66,15 @@ public class PostgresTests : TestFixture
|
|||
public async Task TestForUniqueUserEmail()
|
||||
{
|
||||
using var db = _databaseOperations.CreateScope(nameof(TestForUniqueUserEmail));
|
||||
// try
|
||||
try
|
||||
{
|
||||
var sql = @"
|
||||
INSERT INTO system.users(email, password_hash, security_stamp, email_confirmed,
|
||||
access_failed_count, lockout_enabled,
|
||||
is_active)
|
||||
VALUES(@Email, @PasswordHash, @SecurityStamp, @EmailConfirmed,
|
||||
@AccessFailedCount, @LockoutEnabled, @IsActive)
|
||||
var sql = @"INSERT INTO system.users(email, password_hash, security_stamp, email_confirmed, access_failed_count, lockout_enabled, is_active)
|
||||
VALUES(@Email, @PasswordHash, @SecurityStamp, @EmailConfirmed, @AccessFailedCount, @LockoutEnabled, @IsActive)
|
||||
RETURNING id, created_at, email, is_active";
|
||||
|
||||
var parameters = new
|
||||
{
|
||||
Email = "jarjarbinks22233@mars.com",
|
||||
Email = $"{GetRandomWord()}@mars.com",
|
||||
PasswordHash = "MartianRover2025",
|
||||
SecurityStamp = "MarsOrBust",
|
||||
EmailConfirmed = true,
|
||||
|
|
@ -89,16 +85,17 @@ public class PostgresTests : TestFixture
|
|||
|
||||
var user = await db.Connection.QuerySqlAsync<dynamic>(sql, parameters);
|
||||
|
||||
// user.ShouldNotBeNull();
|
||||
|
||||
//EmailAlreadyRegistreredException
|
||||
//try insert, to test exception
|
||||
var ex = await Should.ThrowAsync<EmailAlreadyRegistreredException>(async () =>
|
||||
await db.Connection.ExecuteAsync(sql, parameters));
|
||||
var ex = await Should.ThrowAsync<Npgsql.PostgresException>(async () =>
|
||||
await db.Connection.QuerySqlAsync<dynamic>(sql, parameters));
|
||||
ex.ConstraintName.ShouldBe("users_email_key");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
db.Error(ex);
|
||||
|
||||
}
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// db.Error(ex);
|
||||
// }
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using PlanTempus.Core.Configurations.JsonConfigProvider;
|
|||
using PlanTempus.Core.ModuleRegistry;
|
||||
using PlanTempus.Core.SeqLogging;
|
||||
using PlanTempus.Database.ModuleRegistry;
|
||||
using CrypticWizard.RandomWordGenerator;
|
||||
|
||||
namespace PlanTempus.X.TDD;
|
||||
|
||||
|
|
@ -22,7 +23,11 @@ public abstract class TestFixture
|
|||
protected TestFixture() : this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public string GetRandomWord()
|
||||
{
|
||||
var myWordGenerator = new WordGenerator();
|
||||
return myWordGenerator.GetWord(WordGenerator.PartOfSpeech.verb);
|
||||
}
|
||||
public TestFixture(string configurationFilePath)
|
||||
{
|
||||
if (configurationFilePath is not null)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=192.168.1.57;Port=5432;Database=ptmain;User Id=sathumper;Password=3911;"
|
||||
"DefaultConnection": "Host=192.168.1.63;Port=5432;Database=ptmain;User Id=sathumper;Password=3911;"
|
||||
},
|
||||
"ApplicationInsights": {
|
||||
"ConnectionString": "InstrumentationKey=07d2a2b9-5e8e-4924-836e-264f8438f6c5;IngestionEndpoint=https://northeurope-2.in.applicationinsights.azure.com/;LiveEndpoint=https://northeurope.livediagnostics.monitor.azure.com/;ApplicationId=56748c39-2fa3-4880-a1e2-24068e791548",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue