Feature: straightmail v0.5.0#4
Open
codeministry wants to merge 27 commits into
Open
Conversation
…Spring Boot 3.5.7 / Java 21)
- **feat(backend): expose additional ports 50003, 50004 in Dockerfile** 🐳
…ead of `client/package.json`
…encies and adapt imports
…ASSPATH references
…nfiguration in README.md
- Add tenant configuration instructions (`TENANTS_CONFIG`) for non-database profiles. - Document breaking changes for template directory structure and tenant subdirectories. - Update Docker Compose examples with new environment variables and volume mappings.
# Conflicts: # backend/src/test/java/com/encircle360/oss/straightmail/AbstractTemplateLoaderTest.java # src/main/java/com/encircle360/oss/straightmail/service/EmailService.java # src/main/java/com/encircle360/oss/straightmail/service/template/AbstractTemplateLoader.java
…rove error logging functionality - Added AbstractTemplateLoaderTest to validate template loading scenarios, covering missing and partial templates. - Enhanced error logging in `AbstractTemplateLoader` to differentiate required vs optional template file handling. - Improved `EmailService` logging to provide better operator visibility for email requests and SMTP dispatch events.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
feat: straightmail v0.5.0 — multi-tenancy, SQLite, API-key auth, Git-sync, four Docker stacks
Summary
This PR introduces multi-tenancy, three authentication modes, Git-sync for templates, SQLite as the default database,
and a restructured Docker Compose setup. Changes span backend, frontend, infrastructure, and CI/CD.
What's new
Multi-tenancy
TenantReconciliationService: tenants declared inapplication.ymlundertenants.config.*are automaticallycreated or updated at startup — zero-touch provisioning, no manual API calls required
GET/POST/PUT/DELETE /api/v1/tenants(admin-only, requiresdatabaseprofile)TenantContextresolves the active tenant from the request on every call; service and business logic layers neverread
HttpServletRequestdirectlyAuthentication modes (
AUTH_MODE)The boolean
auth.enabledflag has been replaced by a three-valueauth.modeproperty:AUTH_MODEoidc(default)api-keyX-API-KEYheader; per-tenant or global SHA-256 hash lookupnoneGit-Sync for templates
GitTemplateSourceProviderloads.ftlfiles from the working tree into a local cache tableTemplate source architecture
Templates are now resolved from up to three independent sources; the first match wins:
databaseprofile).ftlfiles from a mounted host directoryEvery template carries an implicit
source:database,source:file, orsource:gittag — filterable via the API.Encryption at rest
EncryptionService(AES-256-GCM) encrypts all secrets before persistence (SMTP password, Git token, API key hash).Secrets are never returned in plain text by the API. Double-encryption is prevented by checking the stored value before
each write.
SQLite as default database
SQLite (WAL mode, single-file) replaces PostgreSQL as the default. PostgreSQL remains fully supported via environment
variables:
Frontend changes
settings
AUTH_MODE=api-keydeploymentsTenantState,ApiKeyStateadminGuard(tenant admin area),canDeactivateFormGuard(unsaved changes protection)ApiKeyInterceptoraddsX-API-KEYandX-Tenant-IDheaders in API-Key modeInfrastructure changes
Docker Compose
The single root-level
docker-compose.ymlhas been replaced by four mode-specific stacks indocker/:minimal.ymlapikey-sqlite.ymloidc-sqlite.ymloidc-postgres.ymlBuild the JAR first, then start a stack:
See docker/README.md for details.
Helm chart
The Helm chart has been removed from this repository and will be maintained in a dedicated
helm-chartsrepository.Developer experience
application-local.ymlis now gitignored — real credentials can never be accidentally committedapplication-local.yml.exampleadded with placeholder values (ACME tenant,smtp.example.com)application-dev.ymlremoved; useapplication-local.yml(copied from the example) insteadSKIP_FRONTEND_BUILD=trueskips the Angular build for backend-only developmentBreaking changes
auth.enabled: true/falseAUTH_MODE: oidc / api-key / noneclient/frontend/docker-compose.ymlat rootdocker/service/template/TemplateService(monolithic)service/template/provider/(composite providers)controller/MailController(flat)controller/mail/MailController(nested)ENCRYPTION_KEYdatabaseprofile0001typeuuid(PostgreSQL native)varchar(36)— requires manual migration on v0.4.0 PostgreSQL instancesLiquibase note
Changeset
0001changes theidcolumn type fromuuidtovarchar(36)for SQLite compatibility.Existing PostgreSQL deployments (v0.4.0) are affected. If the old
0001changeset has already been applied (which it has on any v0.4.0 installation), Liquibase will detect a checksum mismatch and refuse to start. Before applying this PR to a v0.4.0 PostgreSQL instance, either:idcolumn type fromuuidtovarchar(36), or0001in thedatabasechangelogtable and ensure the column type is compatible.Test coverage
TenantIntegrationTest,TenantSenderEnforcementTest,TemplatesControllerTest,StatusControllerTest,EncryptionServiceTest,TenantServiceTest,TenantReconciliationServiceTest,GitSyncSchedulerTest, and moreChangelog
Backend — [0.5.0]
Added
TenantService,TenantRepository,/v1/tenantsCRUD admin APIApiKeyTenantResolutionFilter) with SHA-256 hashing viaEncryptionServiceAbstractTenantResolutionFilterbase class; JWT and API-key resolution share common logicTenantProperties+TenantReconciliationService(YAML-declared tenantsreconciled at startup)
StartupConfigLogger: logs all resolved configuration at startup with masked secretsauth.modeproperty (oidc|api-key|none) replacing the booleanauth.enabledflagNoAuthTenantResolutionFilterresolves tenant fromX-Tenant-IDheader or falls back todefault
GitSyncStatusRepository) and template cachingGitSyncSchedulerwith initial sync on application startup; ShedLock uses JVM system time for SQLite compatibilityTemplateView.editable) distinguishing DATABASE vs FILE/GIT templatessource:database,source:file,source:git) auto-applied byTemplateServiceeffectiveTagsunifying explicit and source tags for consistent tag-based filteringlogo_url,brand_color) inTenantDTOChanged
jdbc:sqlite:); Liquibase changesets updatedObjectProvider<T>used for all beans conditional on thedatabaseprofilecontroller/mail/,controller/template/,controller/tenant/,service/template/loader/,service/template/provider/@Autowiredfield injection replaced by constructor injection throughoutRemoved
auth.enabledboolean property (superseded byauth.mode)Frontend — [0.5.0]
Added
/api-key-loginpage,ApiKeyState,ApiKeyInterceptorTenantState.isDatabaseModeselector; DB-mode-only actions (New Template, New Tenant) conditionally renderedTemplatesStatewith source-tab filtering (DATABASE/FILE/GIT/ALL) and tag filteringTemplateGridComponentand grid/list view toggle (persisted inUiState)TemplateViewComponentfor GIT/FILE templatessource:gittemplatesDashboardStatetracking Git sync status per tenantFileSyncCard/GitSyncCardcomponents for sync status displayUserAvatar,TenantAvatar,NavIconComponentreusable UI componentsHelpPanelComponent: context-sensitive off-canvas help panel (right panel / bottom sheet on mobile)LocalStorageviaRenderState)templates.spec.ts,tenants.spec.tsautoAuthPlaywright fixture: pre-seeds sessionStorage/localStorage before each testChanged
TranslateModuleimports replaced by standaloneTranslatePipeacross all componentscanDeactivateacross form pagesremunits across all component stylesheetsFixed
mockTenantsE2E helper now mocks/v1/tenants/me(the actualLoadTenantsendpoint) instead of/v1/tenantsautoAuthfixture seeds tenant witheditable: trueso "New Template" / "New Tenant" buttons rendercorrectly
Checklist
application-local.ymlgitignoreddocker compose config)./gradlew compileJava -PskipFrontendBuild=true)NgModulecreated; all Angular components standalonedetectChanges()calls in production Angular code