feat(server): 为内部管理查询添加租户隔离支持
实现共库模式下的租户数据隔离,新增 TenantColumn 字段标识查询表的租户列,添加 internalAdminTenantCondition 函数生成租户过滤条件。修改所有内部管理查询的构建逻辑,在列表和详情查询中自动注入租户条件,防止跨租户数据泄漏。同时更新所有资源查询规格,配置对应表的租户列。
This commit is contained in:
+31
-8
@@ -467,7 +467,12 @@ func serveInternalUserQuery(wrt http.ResponseWriter, req *http.Request, tenantID
|
||||
}
|
||||
if spec, ok := internalAdminQuerySpec("users"); ok {
|
||||
query := spec.Select + " " + spec.From + " WHERE u.id=?"
|
||||
if row, err := store.InternalAdminQueries.QueryOne(tenantID, query, []any{userDBID}); err == nil {
|
||||
args := []any{userDBID}
|
||||
if cond, extra := internalAdminTenantCondition(spec, tenantID); cond != "" {
|
||||
query += cond
|
||||
args = append(args, extra...)
|
||||
}
|
||||
if row, err := store.InternalAdminQueries.QueryOne(tenantID, query, args); err == nil {
|
||||
writeIMSuccess(wrt, req, normalizeInternalAdminRowForAPI(row))
|
||||
return
|
||||
} else {
|
||||
@@ -508,7 +513,12 @@ func serveInternalGroupQuery(wrt http.ResponseWriter, req *http.Request, tenantI
|
||||
}
|
||||
if spec, ok := internalAdminQuerySpec("groups"); ok {
|
||||
query := spec.Select + " " + spec.From + " WHERE t.name=?"
|
||||
if row, err := store.InternalAdminQueries.QueryOne(tenantID, query, []any{topic}); err == nil {
|
||||
args := []any{topic}
|
||||
if cond, extra := internalAdminTenantCondition(spec, tenantID); cond != "" {
|
||||
query += cond
|
||||
args = append(args, extra...)
|
||||
}
|
||||
if row, err := store.InternalAdminQueries.QueryOne(tenantID, query, args); err == nil {
|
||||
writeIMSuccess(wrt, req, normalizeInternalAdminRowForAPI(row))
|
||||
return
|
||||
}
|
||||
@@ -529,9 +539,10 @@ func serveInternalGroupMembersQuery(wrt http.ResponseWriter, req *http.Request,
|
||||
spec := &internalQuerySpec{
|
||||
Select: `SELECT gm.id,gm.topic,gm.user_id,u.state,p.nickname,p.public_account,p.avatar_file_id,p.signature,p.gender,p.region,s.modewant AS mode_want,s.modegiven AS mode_given,s.recvseqid AS recv_seq_id,s.readseqid AS read_seq_id,s.delid AS del_id,
|
||||
gm.role,gm.member_status,gm.nickname AS group_nickname,gm.pinned,gm.mute_notifications,gm.join_source,gm.joined_by,gm.joined_at,gm.left_at,gm.removed_by,gm.version,gm.created_at,gm.updated_at`,
|
||||
From: "FROM im_group_members AS gm LEFT JOIN im_users AS u ON u.id=gm.user_id LEFT JOIN im_user_profiles AS p ON p.user_id=gm.user_id LEFT JOIN im_subscriptions AS s ON s.topic=gm.topic AND s.userid=gm.user_id",
|
||||
DefaultSort: "ORDER BY gm.id DESC",
|
||||
ScopeColumn: "gm.topic",
|
||||
From: "FROM im_group_members AS gm LEFT JOIN im_users AS u ON u.id=gm.user_id LEFT JOIN im_user_profiles AS p ON p.user_id=gm.user_id LEFT JOIN im_subscriptions AS s ON s.topic=gm.topic AND s.userid=gm.user_id",
|
||||
DefaultSort: "ORDER BY gm.id DESC",
|
||||
ScopeColumn: "gm.topic",
|
||||
TenantColumn: "gm.tenant_id",
|
||||
Filters: []internalQueryFilter{
|
||||
{"user_id", "gm.user_id", "=", "uid"},
|
||||
{"role", "gm.role", "=", "string"},
|
||||
@@ -540,7 +551,7 @@ func serveInternalGroupMembersQuery(wrt http.ResponseWriter, req *http.Request,
|
||||
{"eligible_role", "gm.role", "=", "string"},
|
||||
},
|
||||
}
|
||||
query, countQuery, args, page, perPage, err := buildInternalAdminListQuery(req, spec, topic)
|
||||
query, countQuery, args, page, perPage, err := buildInternalAdminListQuery(req, spec, topic, tenantID)
|
||||
if err == nil {
|
||||
if result, queryErr := store.InternalAdminQueries.Query(tenantID, query, countQuery, args, page, perPage); queryErr == nil {
|
||||
writeIMSuccess(wrt, req, map[string]any{
|
||||
@@ -606,7 +617,13 @@ func serveInternalMessageQuery(wrt http.ResponseWriter, req *http.Request, tenan
|
||||
}
|
||||
}
|
||||
spec.Select += ",m.head,JSON_UNQUOTE(m.content) AS content"
|
||||
row, err := store.InternalAdminQueries.QueryOne(tenantID, spec.Select+" "+spec.From+" WHERE "+where, []any{topic, seq})
|
||||
query := spec.Select + " " + spec.From + " WHERE " + where
|
||||
args := []any{topic, seq}
|
||||
if cond, extra := internalAdminTenantCondition(spec, tenantID); cond != "" {
|
||||
query += cond
|
||||
args = append(args, extra...)
|
||||
}
|
||||
row, err := store.InternalAdminQueries.QueryOne(tenantID, query, args)
|
||||
if err != nil {
|
||||
writeInternalQueryError(wrt, req, err)
|
||||
return
|
||||
@@ -633,7 +650,13 @@ func serveInternalFileQuery(wrt http.ResponseWriter, req *http.Request, tenantID
|
||||
return
|
||||
}
|
||||
spec, _ := internalAdminQuerySpec("files")
|
||||
row, err := store.InternalAdminQueries.QueryOne(tenantID, spec.Select+" "+spec.From+" WHERE id=?", []any{fileDBID})
|
||||
query := spec.Select + " " + spec.From + " WHERE id=?"
|
||||
args := []any{fileDBID}
|
||||
if cond, extra := internalAdminTenantCondition(spec, tenantID); cond != "" {
|
||||
query += cond
|
||||
args = append(args, extra...)
|
||||
}
|
||||
row, err := store.InternalAdminQueries.QueryOne(tenantID, query, args)
|
||||
if err != nil {
|
||||
writeInternalQueryError(wrt, req, err)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user