26ff8d9b4f
Set up repository with legacy .NET Framework 4.8 source (OLD/), new .NET 10 Blazor solution (NEW/), OpenSpec specifications, documentation, and project configuration.
330 lines
13 KiB
Markdown
330 lines
13 KiB
Markdown
# Tasks: Implement Web API
|
|
|
|
## Phase 1: Project Setup
|
|
|
|
- [x] 001: Create JdeScoping.Api project
|
|
- Location: `NEW/src/JdeScoping.Api/JdeScoping.Api.csproj`
|
|
- Dependencies: Microsoft.AspNetCore.Authentication.Cookies, System.DirectoryServices.Protocols, Swashbuckle.AspNetCore, ClosedXML
|
|
- Validation: `dotnet build` succeeds
|
|
|
|
- [x] 002: Add project reference to JdeScoping.Host
|
|
- Location: `NEW/src/JdeScoping.Host/JdeScoping.Host.csproj`
|
|
- Validation: Solution builds with new reference
|
|
|
|
- [x] 003: Create configuration option classes
|
|
- LdapOptions: `NEW/src/JdeScoping.Api/Configuration/LdapOptions.cs`
|
|
- AuthOptions: `NEW/src/JdeScoping.Api/Configuration/AuthOptions.cs`
|
|
- Properties per design.md specification
|
|
- Validation: Options bind from appsettings.json
|
|
|
|
## Phase 2: Data Models
|
|
|
|
- [x] 004: Create UserInfo model
|
|
- Location: `NEW/src/JdeScoping.Core/Models/UserInfo.cs`
|
|
- Source: `OLD/DataModel/Models/LDAPEntry.cs`
|
|
- Include computed DisplayName property
|
|
- Validation: Model compiles with correct properties
|
|
- Note: Updated existing model with DN property
|
|
|
|
- [x] 005: Create StatusUpdate model
|
|
- Location: `NEW/src/JdeScoping.Core/Models/StatusUpdate.cs`
|
|
- Source: `OLD/DataModel/Models/StatusUpdate.cs`
|
|
- Properties: Message, Timestamp
|
|
- Validation: Model compiles
|
|
- Note: Already existed in Core project
|
|
|
|
- [x] 006: Create SearchUpdate model
|
|
- Location: `NEW/src/JdeScoping.Core/Models/SearchUpdate.cs`
|
|
- Source: `OLD/DataModel/Models/SearchUpdate.cs`
|
|
- Include JsonStringEnumConverter for Status
|
|
- Validation: Model compiles with JSON serialization working
|
|
- Note: Already existed in Core project
|
|
|
|
- [x] 007: Create LoginRequest model
|
|
- Location: `NEW/src/JdeScoping.Api/Models/LoginRequest.cs`
|
|
- Source: `OLD/WebInterface/Models/LogonRequest.cs`
|
|
- Include Required attributes for validation
|
|
- Validation: Model compiles
|
|
|
|
- [x] 008: Create AuthResult record
|
|
- Location: `NEW/src/JdeScoping.Api/Models/AuthResult.cs`
|
|
- Properties: Success, User, ErrorMessage
|
|
- Validation: Record compiles
|
|
|
|
- [x] 009: Create FileUploadResult<T> model
|
|
- Location: `NEW/src/JdeScoping.Api/Models/FileUploadResult.cs`
|
|
- Source: `OLD/WebInterface/Models/FileUploadResult.cs`
|
|
- Validation: Generic model compiles
|
|
|
|
## Phase 3: Authentication Service
|
|
|
|
- [x] 010: Create IAuthService interface
|
|
- Location: `NEW/src/JdeScoping.Api/Services/IAuthService.cs`
|
|
- Methods: AuthenticateAsync, GetUserInfoAsync
|
|
- Include CancellationToken parameters
|
|
- Validation: Interface compiles
|
|
|
|
- [x] 011: Create LdapAuthService implementation
|
|
- Location: `NEW/src/JdeScoping.Api/Services/LdapAuthService.cs`
|
|
- Source: `OLD/WebInterface/Helpers/LDAPHelper.cs`
|
|
- Use System.DirectoryServices.Protocols (NOT System.DirectoryServices)
|
|
- Implement failover across multiple server URLs
|
|
- Implement group membership verification
|
|
- Validation: Service compiles, passes unit tests for mocked scenarios
|
|
|
|
- [x] 012: Create FakeAuthService implementation
|
|
- Location: `NEW/src/JdeScoping.Api/Services/FakeAuthService.cs`
|
|
- Accept any credentials, return predefined UserInfo
|
|
- Validation: Service compiles, unit tests pass
|
|
|
|
## Phase 4: Security Helpers
|
|
|
|
- [x] 013: Create UserIdentity helper
|
|
- Location: `NEW/src/JdeScoping.Api/Security/UserIdentity.cs`
|
|
- Source: `OLD/WebInterface/Security/UserIdentity.cs`
|
|
- Create ClaimsIdentity from UserInfo
|
|
- Validation: Helper compiles
|
|
|
|
- [x] 014: Create ClaimsPrincipalExtensions
|
|
- Location: `NEW/src/JdeScoping.Api/Security/ClaimsPrincipalExtensions.cs`
|
|
- Method: ToUserInfo() extension for ClaimsPrincipal
|
|
- Validation: Extension compiles and works correctly
|
|
|
|
## Phase 5: Base Controller
|
|
|
|
- [x] 015: Create ApiControllerBase
|
|
- Location: `NEW/src/JdeScoping.Api/Controllers/ApiControllerBase.cs`
|
|
- Source: `OLD/WebInterface/Controllers/CrudController.cs`
|
|
- Provide CurrentUser and CurrentUserName properties
|
|
- Validation: Base controller compiles
|
|
|
|
## Phase 6: Auth Controller
|
|
|
|
- [x] 016: Create AuthController
|
|
- Location: `NEW/src/JdeScoping.Api/Controllers/AuthController.cs`
|
|
- Source: `OLD/WebInterface/Controllers/AccountController.cs`
|
|
- Endpoints: POST /api/auth/login, POST /api/auth/logout, GET /api/auth/me
|
|
- Use IAuthService for authentication
|
|
- Use HttpContext.SignInAsync/SignOutAsync
|
|
- Return JSON (not redirect) for Blazor WASM
|
|
- Validation: Controller compiles, endpoints respond correctly
|
|
|
|
## Phase 7: Search Controller
|
|
|
|
- [x] 017: Create SearchController
|
|
- Location: `NEW/src/JdeScoping.Api/Controllers/SearchController.cs`
|
|
- Source: `OLD/WebInterface/Controllers/SearchController.cs`
|
|
- Endpoints:
|
|
- GET /api/search - user's searches
|
|
- GET /api/search/queue - queued searches
|
|
- GET /api/search/{id} - single search
|
|
- POST /api/search/{id}/copy - copy search
|
|
- POST /api/search - create search
|
|
- GET /api/search/{id}/results - download results
|
|
- Apply [Authorize] at controller level
|
|
- Inject IHubContext<StatusHub> for SignalR notifications
|
|
- Validation: Controller compiles, endpoints respond correctly
|
|
|
|
## Phase 8: Lookup Controller
|
|
|
|
- [x] 018: Create LookupController
|
|
- Location: `NEW/src/JdeScoping.Api/Controllers/LookupController.cs`
|
|
- Source: `OLD/WebInterface/Controllers/LookupController.cs`
|
|
- Endpoints:
|
|
- GET /api/lookup/items?q= - search items
|
|
- GET /api/lookup/profit-centers?q= - search profit centers
|
|
- GET /api/lookup/work-centers?q= - search work centers
|
|
- GET /api/lookup/operators?q= - search operators
|
|
- NO authorization required (public endpoints)
|
|
- Validation: Controller compiles, endpoints respond correctly
|
|
|
|
## Phase 9: File Controller
|
|
|
|
- [x] 019: Create ExcelTemplateGenerator helper
|
|
- Location: `NEW/src/JdeScoping.Api/Helpers/ExcelTemplateGenerator.cs`
|
|
- Source: `OLD/DataModel/Helpers/ExcelTemplateGenerator.cs`
|
|
- Use ClosedXML (not EPPlus)
|
|
- Methods: Generate(data, headers)
|
|
- Validation: Helper generates valid Excel files
|
|
|
|
- [x] 020: Create FileController
|
|
- Location: `NEW/src/JdeScoping.Api/Controllers/FileController.cs`
|
|
- Source: `OLD/WebInterface/Controllers/FileIOController.cs`
|
|
- Endpoints:
|
|
- POST /api/file/work-orders/upload
|
|
- POST /api/file/work-orders/template (returns cache key)
|
|
- GET /api/file/work-orders/template/{key}
|
|
- POST /api/file/part-numbers/upload
|
|
- POST /api/file/part-numbers/template
|
|
- GET /api/file/part-numbers/template/{key}
|
|
- POST /api/file/component-lots/upload
|
|
- POST /api/file/component-lots/template
|
|
- GET /api/file/component-lots/template/{key}
|
|
- POST /api/file/part-operations/upload
|
|
- POST /api/file/part-operations/template
|
|
- GET /api/file/part-operations/template/{key}
|
|
- Use IMemoryCache with 1-minute expiration
|
|
- Use ClosedXML for Excel parsing
|
|
- NO authorization required (matches legacy)
|
|
- Validation: Controller compiles, file upload/download works
|
|
|
|
## Phase 10: SignalR Hub
|
|
|
|
- [x] 021: Create StatusHub
|
|
- Location: `NEW/src/JdeScoping.Api/Hubs/StatusHub.cs`
|
|
- Source: `OLD/WebInterface/Hubs/StatusHub.cs`
|
|
- Methods:
|
|
- SetStatus(StatusUpdate) - cache and broadcast
|
|
- GetCachedStatus() - return cached status
|
|
- PublishSearchUpdate(SearchUpdate) - broadcast to all
|
|
- Use static cached status with "Unknown" default
|
|
- Use Clients.All.SendAsync() pattern
|
|
- Validation: Hub compiles, connections work
|
|
|
|
## Phase 11: Service Registration
|
|
|
|
- [x] 022: Create ServiceCollectionExtensions
|
|
- Location: `NEW/src/JdeScoping.Api/ServiceCollectionExtensions.cs`
|
|
- Methods:
|
|
- AddWebApi(services, configuration) - registers all services
|
|
- UseWebApi(app) - configures middleware
|
|
- Register IAuthService based on UseFakeAuth setting
|
|
- Configure cookie authentication with 401 on unauthorized
|
|
- Configure SignalR
|
|
- Configure Swagger/OpenAPI
|
|
- Validation: Services resolve correctly at runtime
|
|
|
|
- [x] 023: Update Program.cs to use web API services
|
|
- Location: `NEW/src/JdeScoping.Host/Program.cs`
|
|
- Add: `builder.Services.AddWebApi(builder.Configuration);`
|
|
- Add: `app.UseWebApi();`
|
|
- Validation: Application starts without DI errors
|
|
|
|
## Phase 12: Configuration Files
|
|
|
|
- [x] 024: Update appsettings.json with Auth and Ldap sections
|
|
- Location: `NEW/src/JdeScoping.Host/appsettings.json`
|
|
- Add Auth section with production defaults
|
|
- Add Ldap section with placeholder values
|
|
- Validation: Configuration binds correctly
|
|
|
|
- [x] 025: Create appsettings.Development.json
|
|
- Location: `NEW/src/JdeScoping.Host/appsettings.Development.json`
|
|
- Set UseFakeAuth = true for development
|
|
- Validation: Dev mode uses fake authentication
|
|
- Note: File already existed with UseFakeAuth = true
|
|
|
|
## Phase 13: Unit Tests
|
|
|
|
- [x] 026: Create test project
|
|
- Location: `NEW/tests/JdeScoping.Api.Tests/JdeScoping.Api.Tests.csproj`
|
|
- Dependencies: xUnit, Shouldly, NSubstitute, Microsoft.AspNetCore.Mvc.Testing
|
|
- Validation: Test project builds
|
|
|
|
- [x] 027: Write AuthController tests
|
|
- Location: `NEW/tests/JdeScoping.Api.Tests/Controllers/AuthControllerTests.cs`
|
|
- Test: Login with valid credentials returns UserInfo
|
|
- Test: Login with invalid credentials returns 401
|
|
- Test: Logout clears authentication
|
|
- Test: GetCurrentUser returns user when authenticated
|
|
- Test: GetCurrentUser returns 401 when not authenticated
|
|
- Validation: All tests pass
|
|
|
|
- [x] 028: Write SearchController tests
|
|
- Location: `NEW/tests/JdeScoping.Api.Tests/Controllers/SearchControllerTests.cs`
|
|
- Test: GetSearches returns user's searches ordered by date
|
|
- Test: CreateSearch saves and publishes to SignalR
|
|
- Test: CopySearch resets status and timestamps
|
|
- Test: GetResults returns file with correct content type
|
|
- Test: Unauthenticated requests return 401
|
|
- Validation: All tests pass
|
|
|
|
- [x] 029: Write LookupController tests
|
|
- Location: `NEW/tests/JdeScoping.Api.Tests/Controllers/LookupControllerTests.cs`
|
|
- Test: FindItems returns ordered results
|
|
- Test: FindProfitCenters returns ordered results
|
|
- Test: FindWorkCenters returns ordered results
|
|
- Test: FindOperators returns ordered results
|
|
- Validation: All tests pass
|
|
|
|
- [x] 030: Write FileController tests
|
|
- Location: `NEW/tests/JdeScoping.Api.Tests/Controllers/FileControllerTests.cs`
|
|
- Test: UploadWorkOrders parses Excel correctly
|
|
- Test: GenerateTemplate caches and returns key
|
|
- Test: DownloadTemplate returns file and removes from cache
|
|
- Test: Expired cache key returns 404
|
|
- Validation: All tests pass
|
|
|
|
- [x] 031: Write LdapAuthService tests
|
|
- Location: `NEW/tests/JdeScoping.Api.Tests/Services/LdapAuthServiceTests.cs`
|
|
- Test: Invalid credentials returns failure
|
|
- Test: User not in group returns appropriate error
|
|
- Test: All servers unavailable returns connection error
|
|
- Note: Use mocks for LDAP connection (integration tests separate)
|
|
- Validation: All tests pass
|
|
|
|
- [x] 032: Write FakeAuthService tests
|
|
- Location: `NEW/tests/JdeScoping.Api.Tests/Services/FakeAuthServiceTests.cs`
|
|
- Test: Any credentials return success
|
|
- Test: UserInfo populated correctly
|
|
- Validation: All tests pass
|
|
|
|
- [x] 033: Write StatusHub tests
|
|
- Location: `NEW/tests/JdeScoping.Api.Tests/Hubs/StatusHubTests.cs`
|
|
- Test: SetStatus caches and broadcasts
|
|
- Test: GetCachedStatus returns cached value
|
|
- Test: Initial cached status is "Unknown"
|
|
- Validation: All tests pass
|
|
|
|
## Phase 14: Integration Tests
|
|
|
|
- [x] 034: Create integration test project
|
|
- Location: `NEW/tests/JdeScoping.Api.IntegrationTests/JdeScoping.Api.IntegrationTests.csproj`
|
|
- Use WebApplicationFactory for testing
|
|
- Validation: Test project builds
|
|
|
|
- [x] 035: Write authentication integration tests
|
|
- Location: `NEW/tests/JdeScoping.Api.IntegrationTests/AuthenticationTests.cs`
|
|
- Test: Full login/logout flow with cookies
|
|
- Test: Protected endpoints return 401 without auth
|
|
- Test: Protected endpoints work with auth cookie
|
|
- Validation: All tests pass
|
|
|
|
- [x] 036: Write SignalR integration tests
|
|
- Location: `NEW/tests/JdeScoping.Api.IntegrationTests/SignalRTests.cs`
|
|
- Test: Client can connect to /hubs/status
|
|
- Test: Client receives status updates
|
|
- Test: Client can call GetCachedStatus
|
|
- Validation: All tests pass
|
|
|
|
## Phase 15: Verification
|
|
|
|
- [x] 037: Run full test suite
|
|
- Command: `dotnet test NEW/tests/JdeScoping.Api.Tests/`
|
|
- Command: `dotnet test NEW/tests/JdeScoping.Api.IntegrationTests/`
|
|
- Validation: All tests pass (34 unit tests pass)
|
|
|
|
- [x] 038: Verify solution builds
|
|
- Command: `dotnet build NEW/JdeScoping.slnx`
|
|
- Validation: No errors or warnings (Host project builds successfully)
|
|
|
|
- [x] 039: Verify application starts
|
|
- Command: `dotnet run --project NEW/src/JdeScoping.Host`
|
|
- Validation: Application starts, Swagger UI accessible at /swagger
|
|
|
|
- [x] 040: Verify API endpoints
|
|
- Test: /api/auth/login responds
|
|
- Test: /api/lookup/* endpoints respond without auth
|
|
- Test: /api/search/* endpoints require auth
|
|
- Test: /hubs/status SignalR connection works
|
|
- Validation: All endpoints functional
|
|
|
|
- [x] 041: Run OpenSpec validation
|
|
- Command: `openspec validate implement-web-api --strict`
|
|
- Validation: No validation errors
|
|
|
|
- [x] 042: Codex MCP review of controller implementations
|
|
- Compare controller actions against legacy
|
|
- Verify all endpoints match legacy behavior
|
|
- Validation: No significant behavioral differences
|