- Add SolutionService with install/delete/rollback flow, entity provisioning
(customers, assets, devices, dashboards, edges, rule chains, CFs, users),
telemetry emulators, instructions templating, and public customer support
- Add SolutionInstallDialogComponent in home/components/solution with markdown
details display and "Go to main dashboard" navigation
- Update IoT Hub install dialog to open solution dialog on template success
- Add SOLUTION_TEMPLATE type support across frontend (item cards, detail dialog,
installed items table with dashboard entity mapping)
- Add solution instructions button to item detail dialog for installed templates
- Update edge detail URLs and dashboard links for correct CE routing
The alreadyProcessed() method used separate get() and put() calls on the
local cache, allowing concurrent threads in the notification executor pool
to both read null and bypass deduplication, creating duplicate notifications.
Replace with a single compute() call that atomically checks and updates
the cache entry, preventing the race between concurrent trigger processing.
Also fix: discard external cache timestamps that are more than 1 hour in
the future (clock skew protection), and avoid reading back from the SOFT
ref local cache when writing to external cache (GC could null it out).
- Move OR filter predicates to middle-layer WHERE clause where JOIN alias
table references are visible, fixing BadSqlGrammarException
- Use alias name (e.g. alias2) instead of bare column name for entity
field predicates in middle-layer WHERE
- Propagate keyFiltersOperation through BaseEntityService optimization
path and alarm subscription contexts (TbAlarmDataSubCtx, TbAlarmCountSubCtx)
- Replace ThingsboardException with IllegalArgumentException for OR
disabled validation
- Add AlarmCountQuery 3-arg constructor for test convenience
- Add 8 new integration tests: alarm data/count OR, mixed entity field +
attribute OR, string attributes, single filter, 3-way OR, pagination,
and zero-match edge case
- Extract evaluateSingleFilter helper to avoid duplicating filter evaluation logic
- Add 3-arg checkKeyFilters overload accepting ComplexOperation parameter
- OR mode: any matching filter includes entity (short-circuit on first true)
- AND mode: all filters must match (short-circuit on first false, unchanged behavior)
- Null operation defaults to AND for backward compatibility
- Update checkFilters to pass query.getKeyFiltersOperation() through to checkKeyFilters
- Add keyFiltersOperation field to EdqsQuery base class
- Update EdqsCountQuery and EdqsDataQuery constructors to accept and propagate ComplexOperation
- Propagate keyFiltersOperationOrDefault in both toNewQuery overloads in RepositoryUtils
- Add sql.query.key-filters-or-conditions.enabled property to thingsboard.yml
- Add allowKeyFiltersOrConditions field to SystemParams
- Wire config value into SystemInfoController for /api/system/params
- Add validateKeyFiltersOperation to DefaultEntityQueryService
- Add throws ThingsboardException to EntityQueryService interface methods
- Reject OR queries with 400 when feature is disabled
- Add keyFiltersOperation field with null-safe getKeyFiltersOperationOrDefault()
- Add 3-arg constructor to EntityCountQuery for explicit operation
- Add 6-arg constructors to AbstractDataQuery and EntityDataQuery
- Add 7-arg constructor to AlarmDataQuery
- Update next() methods to propagate keyFiltersOperation
- Update buildEntityDataQuery methods to pass operation from alarm queries
- Extract shared parseHostEntries() to deduplicate setAllowedHosts/setAdditionalBlockedHosts
- Add isHostnameAllowed() and propagate hostname allow-list check in resolver
- Move OAuth2 custom mapper URL SSRF validation to save-time (Oauth2ClientDataValidator)
- Remove runtime SSRF checks from CustomOAuth2ClientMapper and GithubOAuth2ClientMapper
(custom URL now validated at save; GitHub emailUrl is server config, not user input)
- Replace example.com with 8.8.8.8 in resolver test to avoid DNS dependency
Add SsrfSafeAddressResolverGroup that validates resolved IPs at Netty
connection time, eliminating the TOCTOU gap where DNS rebinding domains
resolve to safe IPs during validation but to private/metadata IPs at
connection time. Disable HTTP redirects in TbHttpClient to prevent
redirect-based SSRF bypass.
Add allow-list support (SSRF_ALLOWED_HOSTS) to SsrfProtectionValidator
so customers with IoT devices on private networks can whitelist specific
addresses or CIDR ranges while keeping SSRF protection enabled.
Add SSRF validation to MS Teams webhook, custom OAuth2 mapper, and
GitHub OAuth2 mapper endpoints. Log a warning when SSRF protection is
disabled.
- Extract RuleChainDetailsDao from RuleChainDao to reuse JpaAbstractDao
save logic (proper @Version increment, flush, detach)
- Reduce notes column size from 10MB to 1MB in schema and migration
- Catch "value too long" DB error with user-friendly message
- Pass tenantId consistently through the details DAO API
- Exclude content/markdownCss from RuleChainNote toString
- Add tests: save/load notes, update notes, preserve notes on
RuleChain save, remove notes, exceeded size limit
Rename `openConnections`/`connectionsCounter` to `statsName`/`number`
to match DefaultTransportService and avoid misleading future readers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Refactor update/delete endpoints to use installed item's own ID instead of marketplace itemId
- Add SHA-256 checksum comparison to detect local entity modifications before update
- Support force update to skip checksum check when user confirms overwrite
- Add per-type update methods (widget, dashboard, calculated field, rule chain)
- Add entityId field to CalculatedFieldInstalledItemDescriptor
- Replace checkForUpdates with getItemsPublishedVersions API
- Replace getInstalledItemInfos with getInstalledItemIds returning List<UUID>
- Remove unused IotHubInstalledItemInfo class and resolver
- Set metadata version from saved rule chain in install/update flows
- Add entity-modified confirmation dialog in update UI