Aias00 opened a new issue, #7468:
URL: https://github.com/apache/shenyu/issues/7468

   ## Description
   
   The config import flow detects duplicates only against rows that existed 
before the import started. It does not update the in-memory duplicate sets/maps 
after each successful insert, so duplicate business keys inside the same 
uploaded ZIP can slip through.
   
   The reachable endpoint is `POST /configs/import` at 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigsExportImportController.java:131`.
 `ConfigsServiceImpl.configsImport()` creates one `ConfigsImportContext` and 
iterates the handlers for each ZIP item 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java:439-445`).
 Handler order includes auth, metadata, selectors, rules, dicts, proxy 
selectors, discovery, and discovery upstream 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/configs/ConfigsExportImportEnum.java:25-75`).
   
   Several import services share the same pattern:
   
   - `SelectorServiceImpl.importData()` builds `pluginSelectorMap` from 
`selectorMapper.selectAllByNamespaceId(namespace)` once 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java:570`)
 and builds `existSelectorSet` from that snapshot 
(`SelectorServiceImpl.java:583`), but after `create(selectorDTO)` it does not 
add the inserted selector name to the set (`SelectorServiceImpl.java:599-611`).
   - `RuleServiceImpl.importData()` builds `selectorRuleMap` once 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/RuleServiceImpl.java:350`)
 and `existRuleNameSet` from that original map (`RuleServiceImpl.java:368`), 
then inserts without adding the rule name (`RuleServiceImpl.java:380-394`).
   - `MetaDataServiceImpl.importData()` builds `existMetadataPathSet` once 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java:258`)
 and inserts without adding the path (`MetaDataServiceImpl.java:276-278`).
   - `AppAuthServiceImpl.importData()` builds `existAppKeySet` once 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java:358`)
 and inserts without adding the app key (`AppAuthServiceImpl.java:376-383`).
   - `ShenyuDictServiceImpl.importData()` builds `dictTypeMap` once 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ShenyuDictServiceImpl.java:115`)
 and rebuilds the set from that original map for each row 
(`ShenyuDictServiceImpl.java:123-127`), then inserts without updating it 
(`ShenyuDictServiceImpl.java:135`).
   - `ProxySelectorServiceImpl.importData()` builds `pluginProxySelectorMap` 
once 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java:553`)
 and inserts without updating it (`ProxySelectorServiceImpl.java:574-581`).
   - `DiscoveryServiceImpl.importData()` builds `pluginDiscoveryMap` once 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java:490`)
 and inserts without updating it (`DiscoveryServiceImpl.java:510-514`).
   - `DiscoveryUpstreamServiceImpl.importData()` builds 
`discoveryHandlerUpstreamMap` once 
(`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java:361`)
 and inserts without updating it (`DiscoveryUpstreamServiceImpl.java:379-384`).
   
   The schema does not enforce business uniqueness for several of these tables. 
For example, `selector`, `rule`, `app_auth`, `proxy_selector`, and `discovery` 
have only primary-key constraints in `db/init/mysql/schema.sql:2176`, `:2132`, 
`:92`, `:2470`, and `:2414`. Other tables have unique constraints that can fail 
late, such as `shenyu_dict` (`db/init/mysql/schema.sql:2222-2234`) and 
`discovery_upstream` (`db/init/mysql/schema.sql:2449-2462`).
   
   ## Trigger
   
   Upload a config ZIP where a file contains duplicate business keys that do 
not already exist in the target namespace. Examples:
   
   - two selectors with the same remapped plugin id and selector name;
   - two rules with the same remapped selector id and rule name;
   - two metadata rows with the same path;
   - two app auth rows with the same app key;
   - two dict rows with the same type/code/name;
   - two proxy selectors with the same plugin/name;
   - two discoveries with the same plugin/name;
   - two discovery upstreams with the same remapped handler/url.
   
   ## Expected behavior
   
   The import should detect duplicates inside the uploaded archive and report 
the later row as failed, or map the later row to the first inserted row 
consistently without writing duplicate business records.
   
   ## Actual behavior
   
   Each service compares each row only against the original database snapshot. 
The first duplicate row is inserted, but the duplicate set/map is not updated, 
so the second row is treated as new. Depending on the table, the import either 
persists duplicate business records or fails late with a database unique-key 
exception instead of producing a row-level duplicate failure.
   
   ## Impact
   
   Duplicate selectors, rules, metadata, app auth entries, proxy selectors, or 
discoveries can be imported into a namespace even though the import code 
attempts to prevent duplicates. For tables with database unique keys, a 
duplicate inside one archive can abort the import with a low-level database 
error instead of returning a clean import result.
   
   ## Suggested fix
   
   Pre-validate each import list for duplicate business keys before writing, or 
add each successful insert to the in-memory duplicate set/map immediately after 
the insert succeeds. For namespace imports that remap ids, compute the 
duplicate key from the remapped plugin/selector/handler id.
   
   ## Related existing issues
   
   This is distinct from #6465, which only covers discovery upstream duplicate 
checks before handler-id remapping, and from #6697, which covers transaction 
boundaries for dictionary import. It is also distinct from older primary-key/id 
conflict reports such as #5826 and #5895. This issue is about duplicate 
business keys inside the same uploaded archive.
   
   
   ## Reviewed Revision And Validation
   
   Apache ShenYu 2.7.2-SNAPSHOT, master at 
a89b6a2338c24e978428b731e8f1edce86022418. Severity: medium. Confidence: high.
   
   Independent actual SelectorService import test reproduced two 
same-business-key inserts; wider sibling patterns were inspected and should be 
covered when fixing.
   
   Current source references:
   
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/ConfigsExportImportController.java:131`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ConfigsServiceImpl.java:439`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/configs/ConfigsExportImportEnum.java:25`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java:570`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SelectorServiceImpl.java:583`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/RuleServiceImpl.java:350`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/RuleServiceImpl.java:368`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/MetaDataServiceImpl.java:258`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/AppAuthServiceImpl.java:358`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ShenyuDictServiceImpl.java:115`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/ProxySelectorServiceImpl.java:553`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java:490`
   - 
`shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java:361`
   - `db/init/mysql/schema.sql:2176`
   - `db/init/mysql/schema.sql:2132`
   - `db/init/mysql/schema.sql:92`
   - `db/init/mysql/schema.sql:2222`
   - `db/init/mysql/schema.sql:2449`
   
   No implementation fix or full deployed end-to-end validation was performed 
by this review. Source-flow and runtime evidence are distinguished above.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to