mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
fix(conversation): use notLikeLeft to avoid over-broad malformed-id filter
The previous notLike(column, "%:") form auto-wraps the value with extra %
on both sides AND escapes the user-supplied %, producing a %%:% pattern
that matches any id CONTAINING a colon — silently filtering out every
webchat:<key>:<visitor>, feishu:<chatId>, cron:<jobId> conversation from
the admin list / page. The frontend sidebar ends up empty.
Switch to notLikeLeft(column, ":") which only prepends the wildcard,
giving the intended NOT LIKE '%:' (does not end with a colon).
Strengthen the three malformedIdGuard tests to assert on the bound param
value ("%:" — ends-with colon) in addition to the SQL keyword, so this
regression cannot return silently. The assertions must call
getTargetSql() first to trigger MyBatis-Plus's nested-wrapper param
merge — getParamNameValuePairs() is empty on the parent until then.
This commit is contained in:
parent
f70e56cfc3
commit
7c36b0d752
@ -210,9 +210,18 @@ public class ConversationService {
|
||||
* Showing them in the console surfaces threads that 500/403 on open
|
||||
* because the trailing ":" makes some reverse proxies strip the path
|
||||
* tail (issue #369).
|
||||
*
|
||||
* <p>Uses {@code notLikeLeft} rather than {@code notLike(...,"%:")}: the
|
||||
* latter auto-wraps the value with extra {@code %} on both sides AND
|
||||
* escapes the user-supplied {@code %}, producing a {@code %%:%} pattern
|
||||
* that matches <em>any id containing a colon</em> — silently filtering
|
||||
* out every {@code webchat:…}, {@code feishu:…}, {@code cron:…}
|
||||
* conversation from the list. {@code notLikeLeft} only prepends the
|
||||
* wildcard, giving the intended {@code NOT LIKE '%:'} ("does not end
|
||||
* with a colon").
|
||||
*/
|
||||
private void applyMalformedIdGuard(LambdaQueryWrapper<ConversationEntity> w) {
|
||||
w.notLike(ConversationEntity::getConversationId, "%:");
|
||||
w.notLikeLeft(ConversationEntity::getConversationId, ":");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -156,12 +156,12 @@ class ConversationServiceWebchatVisibilityTest {
|
||||
|
||||
service.listConversations("admin", 1L, true);
|
||||
|
||||
// Assert on the rendered SQL (not the param values, which MyBatis-Plus
|
||||
// percent-escapes internally) so the test stays independent of that
|
||||
// implementation detail.
|
||||
String sql = captor.getValue().getTargetSql().toLowerCase();
|
||||
assertThat(sql).contains("not like");
|
||||
assertThat(sql).contains("conversation_id");
|
||||
// The bound LIKE pattern must be exactly "%:" (ends-with colon), not
|
||||
// "%%:%" (contains colon). The earlier notLike("%:") form produced
|
||||
// the latter via MyBatis-Plus auto-wrapping + percent-escape, which
|
||||
// filtered out every webchat:… / feishu:… / cron:… conversation.
|
||||
assertThat(captor.getValue().getTargetSql().toLowerCase()).contains("not like");
|
||||
assertThat(captor.getValue().getParamNameValuePairs().values()).contains("%:");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -175,9 +175,10 @@ class ConversationServiceWebchatVisibilityTest {
|
||||
|
||||
service.pageConversations("admin", 1L, 1, 20, null);
|
||||
|
||||
String sql = captor.getValue().getTargetSql().toLowerCase();
|
||||
assertThat(sql).contains("not like");
|
||||
assertThat(sql).contains("conversation_id");
|
||||
// Force the nested-wrapper param merge: getParamNameValuePairs() is
|
||||
// empty until getTargetSql() (or equivalent) has been called once.
|
||||
assertThat(captor.getValue().getTargetSql().toLowerCase()).contains("not like");
|
||||
assertThat(captor.getValue().getParamNameValuePairs().values()).contains("%:");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -189,9 +190,9 @@ class ConversationServiceWebchatVisibilityTest {
|
||||
|
||||
service.listConversations("admin", 1L); // strict 2-arg
|
||||
|
||||
String sql = captor.getValue().getTargetSql().toLowerCase();
|
||||
assertThat(sql).contains("not like");
|
||||
assertThat(sql).contains("conversation_id");
|
||||
// Force the nested-wrapper param merge before checking values.
|
||||
assertThat(captor.getValue().getTargetSql().toLowerCase()).contains("not like");
|
||||
assertThat(captor.getValue().getParamNameValuePairs().values()).contains("%:");
|
||||
}
|
||||
|
||||
private static UserEntity user(String role) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user