The Complaint Tracking System (CTS) is an online application to allow EPD staff to enter, assign, review, and close complaints received from the public.
Public complaints are time-critical and high-profile public information. The CTS is used by staff throughout EPD.
- The application will allow EPD staff to enter new complaints, review and update existing complaints, and remove complaints erroneously entered.
- The admin side of the application will be restricted to authenticated EPD employees.
- A public website will be available for reviewing or searching for complaints.
The solution contains the following projects:
- Domain — A class library containing the data models, business logic, and repository interfaces.
- AppServices — A class library containing the services used by an application to interact with the domain.
- LocalRepository — A class library implementing the repositories and data stores using static in-memory test data (for local development).
- EfRepository — A class library implementing the repositories and data stores using Entity Framework and a database (as specified by the configured connection string).
- WebApp — The front end web application and API.
- TestData — A class library containing test data for development and testing.
There are also corresponding unit test projects for each (not counting the TestData project).
The following settings section configures the data stores, authentication, and other settings for development purposes.
To work with these settings, add an appsettings.Development.json file in the root of the WebApp folder with a
DevSettings section, and make your changes there. Here's a sample appsettings.Development.json file to start out:
{
"DevSettings": {
"UseDevSettings": true,
"BuildDatabase": false,
"UseEfMigrations": false,
"EnableTestUser": true,
"LocalUserIsAuthenticated": true,
"TestUserRoles": [
"Staff",
"SiteMaintenance"
],
"UseSecurityHeadersInDev": false,
"EnableWebOptimizerInDev": false
}
}- UseDevSettings — Indicates whether the following Dev settings should be applied.
- BuildDatabase
- When
true, theEfRepositoryproject is used. A SQL Server database is created, and data is seeded from theTestDataproject. - When
false, theLocalRepositoryproject is used. In-memory data is initialized from theTestDataproject.
- When
- UseEfMigrations — Applies Entity Framework database migrations when
true. Whenfalse, the database is created directly based on theDbContext. (Only applies ifBuildDatabaseistrue.)
- EnableTestUser — If
true, a test user account will be available for development purposes. - TestUserIsAuthenticated — Simulates a successful login with a test account when
true. Simulates a failed login whenfalse. (Only applies ifEnableTestUserisfalse.) - TestUserRoles — Adds the listed App Roles to the logged-in account. (Only applies if
TestUserIsAuthenticatedistrue.)
- UseSecurityHeadersInDev — Sets whether to include HTTP security headers when running in the Development environment.
- EnableWebOptimizerInDev — Sets whether to enable the WebOptimizer middleware for bundling and minification of CSS and JavaScript files when running in the Development environment.
In a production or staging environment, UseDevSettings is automatically set to false regardless of what is specified
in the appsettings.json file.
Connection Strings for both a DefaultConnection and a MigrationConnection must be specified.
- The
DefaultConnectionis used for normal app connectivity. The account only requires DML rights on the database. - The
MigrationConnectionis only used for applying Entity Framework migrations. The account requires DDL plus select and insert rights on the database.
The login providers must be enabled and configured. Currently, Okta and (Azure) Entra ID are available in the application.
- To enable authentication using Entra ID, the app must be registered in the Azure portal and configured in the
AzureAdsettings section.
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"CallbackPath": "/signin-oidc",
"TenantId": "[Enter the Directory (tenant) ID from the Azure portal]",
"ClientId": "[Enter the Application (client) ID from the Azure portal]"
}
}- To enable Okta, the app must be registered in the Okta portal and configured in the
Oktasettings section.
{
"Okta": {
"OktaDomain": "https://${yourOktaDomain}",
"ClientId": "${clientId}",
"ClientSecret": "${clientSecret}",
"AuthorizationServerId": "default"
}
}- Finally, the login providers must be enabled in the
EnabledLoginProviderssection along with the allowed Okta organization ID or Entra Tenant ID.
{
"EnabledLoginProviders": [
{
"Name": "EntraId",
"Id": "tenant-1-id"
},
{
"Name": "EntraId",
"Id": "tenant-2-id"
},
{
"Name": "Okta",
"Id": "okta-id"
}
]
}User roles can be seeded using the SeedUserRoles setting. The roles are added to the user's account the first time
they log in. For example:
{
"SeedUserRoles": [
{
"User": "[email protected]",
"Roles": [
"UserAdmin",
"Staff"
]
}
]
}Here's a visualization of how the settings configure data storage at runtime.
flowchart LR
subgraph SPL["'BuildDatabase' = false"]
direction LR
D[Domain]
T["Test Data (in memory)"]
R[Local Repositories]
A([App Services])
A --> R
R --> T
T --> D
end
flowchart LR
subgraph SPB["'BuildDatabase' = true"]
direction LR
D[Domain]
T[Test Data]
R[EF Repositories]
A([App Services])
B[(Database)]
R --> B
A --> R
T -->|Seed| B
B --> D
end
flowchart LR
subgraph SPD["Production or staging environment"]
direction LR
D[Domain]
R[EF Repositories]
A([App Services])
B[(Database)]
A --> R
R --> B
B --> D
end
