feat(server): 使用Marketing Authorization DB替换部分创作者查询逻辑
- 在server启动时新增Marketing Authorization数据库连接及连接池配置 - 新增router参数以支持Marketing Authorization数据库传递 - CreatorsAPI使用Marketing Authorization数据库替代原marketing数据库查询 - 优化CreatorsAPI查询逻辑,直接查询admin_user表,简化多库回退查询 - 更新配置文件支持Marketing Authorization数据库的DSN配置项 - 相关路由处理器参数调整,确保创作者相关接口走授权库查询逻辑
This commit is contained in:
parent
f936e31cd6
commit
cf9ae5d3f0
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
|
@ -41,13 +42,25 @@ func main() {
|
|||
}
|
||||
// apply pool settings from env for Marketing
|
||||
db.ApplyPoolFromEnv(marketing, "MARKETING_DB_")
|
||||
// Marketing Authorization DB for creators
|
||||
var marketingAuth *sql.DB
|
||||
if cfg.MarketingAuthorizationDB.DSN() != "" {
|
||||
marketingAuth, err = db.ConnectMySQL(cfg.MarketingAuthorizationDB.DSN())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
db.ApplyPoolFromEnv(marketingAuth, "MARKETING_AUTH_DB_")
|
||||
log.Println("connecting Marketing Authorization MySQL:", cfg.MarketingAuthorizationDB.Host+":"+cfg.MarketingAuthorizationDB.Port, "db", cfg.MarketingAuthorizationDB.Name)
|
||||
} else {
|
||||
marketingAuth = marketing // fallback
|
||||
}
|
||||
meta, err := db.ConnectMySQL(cfg.YMTTestDB.DSN())
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// apply pool settings from env for Meta (templates/jobs)
|
||||
db.ApplyPoolFromEnv(meta, "YMT_TEST_DB_")
|
||||
r := api.NewRouter(meta, marketing, ymt)
|
||||
r := api.NewRouter(meta, marketing, marketingAuth, ymt)
|
||||
addr := ":" + func() string {
|
||||
s := cfg.Port
|
||||
if s == "" {
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ import (
|
|||
)
|
||||
|
||||
type CreatorsAPI struct {
|
||||
marketing *sql.DB
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
func CreatorsHandler(marketing *sql.DB) http.Handler {
|
||||
api := &CreatorsAPI{marketing: marketing}
|
||||
func CreatorsHandler(db *sql.DB) http.Handler {
|
||||
api := &CreatorsAPI{db: db}
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
p := strings.TrimPrefix(r.URL.Path, "/api/creators")
|
||||
if r.Method == http.MethodGet && p == "" {
|
||||
|
|
@ -33,20 +33,23 @@ func (a *CreatorsAPI) list(w http.ResponseWriter, r *http.Request) {
|
|||
limit = n
|
||||
}
|
||||
}
|
||||
sql1 := "SELECT DISTINCT user_id, COALESCE(user_name, '') AS name FROM activity WHERE user_id IS NOT NULL"
|
||||
// 查询 admin_user 表的 id 和 real_name
|
||||
sqlStr := "SELECT id, COALESCE(real_name, '') AS name FROM `admin_user` WHERE delete_time = 0"
|
||||
args := []interface{}{}
|
||||
if q != "" {
|
||||
sql1 += " AND (CAST(user_id AS CHAR) LIKE ? OR user_name LIKE ?)"
|
||||
sqlStr += " AND (CAST(id AS CHAR) LIKE ? OR real_name LIKE ?)"
|
||||
like := "%" + q + "%"
|
||||
args = append(args, like, like)
|
||||
}
|
||||
sql1 += " ORDER BY user_id ASC LIMIT ?"
|
||||
sqlStr += " ORDER BY id ASC LIMIT ?"
|
||||
args = append(args, limit)
|
||||
rows, err := a.marketing.Query(sql1, args...)
|
||||
out := []map[string]interface{}{}
|
||||
used := map[int64]struct{}{}
|
||||
if err == nil {
|
||||
rows, err := a.db.Query(sqlStr, args...)
|
||||
if err != nil {
|
||||
fail(w, r, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
out := []map[string]interface{}{}
|
||||
for rows.Next() {
|
||||
var id sql.NullInt64
|
||||
var name sql.NullString
|
||||
|
|
@ -56,103 +59,12 @@ func (a *CreatorsAPI) list(w http.ResponseWriter, r *http.Request) {
|
|||
if !id.Valid {
|
||||
continue
|
||||
}
|
||||
if _, ok := used[id.Int64]; ok {
|
||||
continue
|
||||
}
|
||||
used[id.Int64] = struct{}{}
|
||||
|
||||
n := strings.TrimSpace(name.String)
|
||||
if n == "" {
|
||||
n = strconv.FormatInt(id.Int64, 10)
|
||||
}
|
||||
display := fmt.Sprintf("%s(%d)", n, id.Int64)
|
||||
|
||||
m := map[string]interface{}{"id": id.Int64, "name": display}
|
||||
out = append(out, m)
|
||||
}
|
||||
}
|
||||
if err != nil || len(out) == 0 {
|
||||
sqlPlan := "SELECT DISTINCT creator, COALESCE(creator_name, '') AS name FROM plan WHERE creator IS NOT NULL"
|
||||
argsPlan := []interface{}{}
|
||||
if q != "" {
|
||||
sqlPlan += " AND (CAST(creator AS CHAR) LIKE ? OR creator_name LIKE ?)"
|
||||
like := "%" + q + "%"
|
||||
argsPlan = append(argsPlan, like, like)
|
||||
}
|
||||
sqlPlan += " ORDER BY creator ASC LIMIT ?"
|
||||
argsPlan = append(argsPlan, limit)
|
||||
rowsPlan, errPlan := a.marketing.Query(sqlPlan, argsPlan...)
|
||||
if errPlan == nil {
|
||||
defer rowsPlan.Close()
|
||||
tmp := []map[string]interface{}{}
|
||||
usedPlan := map[int64]struct{}{}
|
||||
for rowsPlan.Next() {
|
||||
var id sql.NullInt64
|
||||
var name sql.NullString
|
||||
if err := rowsPlan.Scan(&id, &name); err != nil {
|
||||
continue
|
||||
}
|
||||
if !id.Valid {
|
||||
continue
|
||||
}
|
||||
if _, ok := usedPlan[id.Int64]; ok {
|
||||
continue
|
||||
}
|
||||
usedPlan[id.Int64] = struct{}{}
|
||||
|
||||
n := strings.TrimSpace(name.String)
|
||||
if n == "" {
|
||||
n = strconv.FormatInt(id.Int64, 10)
|
||||
}
|
||||
display := fmt.Sprintf("%s(%d)", n, id.Int64)
|
||||
|
||||
tmp = append(tmp, map[string]interface{}{"id": id.Int64, "name": display})
|
||||
}
|
||||
if len(tmp) > 0 {
|
||||
out = tmp
|
||||
}
|
||||
}
|
||||
if len(out) == 0 {
|
||||
sql2 := "SELECT DISTINCT creator, '' AS name FROM `order` WHERE creator IS NOT NULL"
|
||||
args2 := []interface{}{}
|
||||
if q != "" {
|
||||
sql2 += " AND CAST(creator AS CHAR) LIKE ?"
|
||||
args2 = append(args2, "%"+q+"%")
|
||||
}
|
||||
sql2 += " ORDER BY creator ASC LIMIT ?"
|
||||
args2 = append(args2, limit)
|
||||
rows2, err2 := a.marketing.Query(sql2, args2...)
|
||||
if err2 != nil {
|
||||
fail(w, r, http.StatusInternalServerError, err2.Error())
|
||||
return
|
||||
}
|
||||
defer rows2.Close()
|
||||
out = out[:0]
|
||||
usedOrder := map[int64]struct{}{}
|
||||
for rows2.Next() {
|
||||
var id sql.NullInt64
|
||||
var name sql.NullString
|
||||
if err := rows2.Scan(&id, &name); err != nil {
|
||||
continue
|
||||
}
|
||||
if !id.Valid {
|
||||
continue
|
||||
}
|
||||
if _, ok := usedOrder[id.Int64]; ok {
|
||||
continue
|
||||
}
|
||||
usedOrder[id.Int64] = struct{}{}
|
||||
|
||||
n := strings.TrimSpace(name.String)
|
||||
if n == "" {
|
||||
n = strconv.FormatInt(id.Int64, 10)
|
||||
}
|
||||
display := fmt.Sprintf("%s(%d)", n, id.Int64)
|
||||
|
||||
m := map[string]interface{}{"id": id.Int64, "name": display}
|
||||
out = append(out, m)
|
||||
}
|
||||
}
|
||||
out = append(out, map[string]interface{}{"id": id.Int64, "name": display})
|
||||
}
|
||||
ok(w, r, out)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"os"
|
||||
)
|
||||
|
||||
func NewRouter(metaDB *sql.DB, marketingDB *sql.DB, ymtDB *sql.DB) http.Handler {
|
||||
func NewRouter(metaDB *sql.DB, marketingDB *sql.DB, marketingAuthDB *sql.DB, ymtDB *sql.DB) http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/api/templates", withAccess(withTrace(TemplatesHandler(metaDB, marketingDB))))
|
||||
mux.Handle("/api/templates/", withAccess(withTrace(TemplatesHandler(metaDB, marketingDB))))
|
||||
|
|
@ -15,8 +15,8 @@ func NewRouter(metaDB *sql.DB, marketingDB *sql.DB, ymtDB *sql.DB) http.Handler
|
|||
mux.Handle("/api/metadata/fields", withAccess(withTrace(MetadataHandler(metaDB, marketingDB, ymtDB))))
|
||||
mux.Handle("/api/fields", withAccess(withTrace(FieldsHandler(marketingDB, ymtDB))))
|
||||
mux.Handle("/api/fields/", withAccess(withTrace(FieldsHandler(marketingDB, ymtDB))))
|
||||
mux.Handle("/api/creators", withAccess(withTrace(CreatorsHandler(marketingDB))))
|
||||
mux.Handle("/api/creators/", withAccess(withTrace(CreatorsHandler(marketingDB))))
|
||||
mux.Handle("/api/creators", withAccess(withTrace(CreatorsHandler(marketingAuthDB))))
|
||||
mux.Handle("/api/creators/", withAccess(withTrace(CreatorsHandler(marketingAuthDB))))
|
||||
mux.Handle("/api/resellers", withAccess(withTrace(ResellersHandler(marketingDB))))
|
||||
mux.Handle("/api/resellers/", withAccess(withTrace(ResellersHandler(marketingDB))))
|
||||
mux.Handle("/api/plans", withAccess(withTrace(PlansHandler(marketingDB))))
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ type DB struct {
|
|||
type App struct {
|
||||
Port string `yaml:"port"`
|
||||
MarketingDB DB `yaml:"marketing_db"`
|
||||
MarketingAuthorizationDB DB `yaml:"marketing_authorization_db"`
|
||||
YMTDB DB `yaml:"ymt_db"`
|
||||
YMTTestDB DB `yaml:"ymt_test_db"`
|
||||
YMTKeyDecryptKeyB64 string `yaml:"ymt_key_decrypt_key_b64"`
|
||||
|
|
|
|||
Loading…
Reference in New Issue