From 5ff2e78a86fb09e9398819b3732677c606b47c54 Mon Sep 17 00:00:00 2001 From: Thun_Ann <2865813065@qq.com> Date: Sun, 23 Feb 2025 16:42:27 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E6=A8=A1=E5=9D=97=E7=9A=84=E8=AF=BB=E5=86=99?= =?UTF-8?q?=E6=93=8D=E4=BD=9Capi=E5=8F=8A=E9=85=8D=E7=BD=AE=E9=A1=B9?= =?UTF-8?q?=E8=8E=B7=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/api.go | 79 ++++++++- database/database.go | 407 +++++++++++++++++++++++++++++++++++-------- wba/wind.go | 10 ++ 3 files changed, 420 insertions(+), 76 deletions(-) diff --git a/core/api.go b/core/api.go index e4ed3bf..de22d21 100644 --- a/core/api.go +++ b/core/api.go @@ -2,6 +2,7 @@ package core import ( "ProjectWIND/LOG" + "ProjectWIND/database" "ProjectWIND/wba" "crypto/rand" "fmt" @@ -795,7 +796,83 @@ func (a *apiInfo) Log(content string, args ...interface{}) { } //database模块 -//TODO: 数据库模块待实现 +//数据库部分允许字符串变量的读写操作,允许获取配置项操作 + +func (a *apiInfo) VarSet(app wba.AppInfo, datamap string, unit string, id string, key string, value string) { + database.Set(app, datamap, unit, id, key, value) +} + +func (a *apiInfo) VarGet(app wba.AppInfo, datamap string, unit string, id string, key string) (string, bool) { + res, ok := database.Get(app, datamap, unit, id, key, false) + if !ok { + return "", false + } + resStr, ok := res.(string) + if !ok { + return "", false + } + return resStr, true +} + +func (a *apiInfo) GetIntConfig(app wba.AppInfo, datamap string, key string) (int64, bool) { + res, ok := database.Get(app, datamap, "config", "number", key, true) + if !ok { + return 0, false + } + resInt, ok := res.(int64) + if !ok { + return 0, false + } + return resInt, true +} + +func (a *apiInfo) GetStringConfig(app wba.AppInfo, datamap string, key string) (string, bool) { + res, ok := database.Get(app, datamap, "config", "string", key, true) + if !ok { + return "", false + } + resStr, ok := res.(string) + if !ok { + return "", false + } + return resStr, true +} + +func (a *apiInfo) GetFloatConfig(app wba.AppInfo, datamap string, key string) (float64, bool) { + res, ok := database.Get(app, datamap, "config", "float", key, true) + if !ok { + return 0, false + } + resFloat, ok := res.(float64) + if !ok { + return 0, false + } + return resFloat, true +} + +func (a *apiInfo) GetIntSliceConfig(app wba.AppInfo, datamap string, key string) ([]int64, bool) { + res, ok := database.Get(app, datamap, "config", "number_slice", key, true) + if !ok { + return nil, false + } + resSlice, ok := res.([]int64) + if !ok { + return nil, false + } + return resSlice, true +} + +func (a *apiInfo) GetStringSliceConfig(app wba.AppInfo, datamap string, key string) ([]string, bool) { + res, ok := database.Get(app, datamap, "config", "string_slice", key, true) + if !ok { + return nil, false + } + resSlice, ok := res.([]string) + if !ok { + return nil, false + } + return resSlice, true +} // 文件管理模块 //TODO: 文件管理模块待实现 diff --git a/database/database.go b/database/database.go index 8df7d75..8c1c962 100644 --- a/database/database.go +++ b/database/database.go @@ -2,6 +2,7 @@ package database import ( "ProjectWIND/LOG" + "ProjectWIND/wba" "encoding/json" "errors" "os" @@ -11,6 +12,9 @@ import ( "time" ) +const address = "./data/database/datamaps.wdb" +const core = "./data/core.json" + type unit struct { Id string Data map[string]string @@ -20,24 +24,76 @@ type User unit type Group unit type Global unit -type Database struct { - Id string - Users map[string]User - Groups map[string]Group - Global map[string]Global +type Configs struct { + Number map[string]int64 + String map[string]string + Float map[string]float64 + Number_Slice map[string][]int64 + String_Slice map[string][]string + Hash string } -func newDatabase(id string) Database { - // 创建数据库 - db := &Database{ - Id: id, - Users: make(map[string]User), - Groups: make(map[string]Group), - Global: make(map[string]Global), +type Datamap struct { + Id string + Permission string + Users map[string]User + Groups map[string]Group + Global map[string]Global + Configs Configs +} + +type Database struct { + Datamaps map[string]Datamap +} + +func newDatamap(id string) Datamap { + // 创建数据表 + db := &Datamap{ + Id: id, + Permission: "private", + Users: make(map[string]User), + Groups: make(map[string]Group), + Global: make(map[string]Global), + Configs: Configs{ + Number: make(map[string]int64), + String: make(map[string]string), + Float: make(map[string]float64), + Number_Slice: make(map[string][]int64), + String_Slice: make(map[string][]string), + Hash: "", + }, } return *db } +func newDatabase() Database { + // 创建数据库 + db := &Database{ + Datamaps: make(map[string]Datamap), + } + return *db +} + +func (this *Database) addDatamap(id string) { + // 创建新数据表 + db := newDatamap(id) + this.Datamaps[id] = db +} + +// func hash(word string) string { +// hash, err := bcrypt.GenerateFromPassword([]byte(word), bcrypt.DefaultCost) +// if err != nil { +// LOG.ERROR("[ERROR]Error while hash password: %v", err) +// return "" +// } +// return string(hash) +// } + +// func hashCheck(word string, hash string) bool { +// err := bcrypt.CompareHashAndPassword(hash, []byte(word)) +// return err == nil +// } + func folderCheck(filename string) { if _, err := os.Stat(filename); os.IsNotExist(err) { err := os.MkdirAll(filename, 0755) @@ -90,6 +146,29 @@ func printContent(file string) (string, error) { } } +func getCorePassword() string { + // 获取核心密码 + filename := core + fileCheck(filename) + dataJson, err := printContent(filename) + if err != nil { + LOG.ERROR("[WARNING]Error while read file %s: %v") + return "" + } + config := make(map[string]string) + err = json.Unmarshal([]byte(dataJson), config) + if err != nil { + LOG.WARN("[WARNING]Error while unmarshal data: %v", err) + return "" + } + password, ok := config["password"] + if !ok { + LOG.WARN("[WARNING]Password not found in core.json") + return "" + } + return password +} + func saveData(db *Database) error { // 保存数据到文件 dataJson, err := json.Marshal(db) @@ -97,7 +176,7 @@ func saveData(db *Database) error { LOG.ERROR("[ERROR]:Error while marshal data: %v", err) return err } - filename := "./database/" + db.Id + ".wdb" + filename := address file, err := os.Create(filename) if err != nil { LOG.ERROR("[ERROR]:Error while create file %s: %v", filename, err) @@ -109,7 +188,7 @@ func saveData(db *Database) error { func loadData(db *Database) error { // 读取配置文件 - filename := "./database/" + db.Id + ".wdb" + filename := address fileCheck(filename) dataJson, err := printContent(filename) if err != nil { @@ -128,11 +207,181 @@ func loadData(db *Database) error { var DB *Database -func dataGet(db *Database, category string, id string, key string) (string, bool) { - // 查询数据 - switch category { +func dataSet(datamap string, unit string, id string, key string, value interface{}, allowed bool) { + // 修改数据 + dm, ok := DB.Datamaps[datamap] + if !ok { + // 创建新数据表 + DB.Datamaps[datamap] = newDatamap(datamap) + dm = DB.Datamaps[datamap] + } + if !allowed && dm.Permission != "private" { + LOG.WARN("[WARNING]:Permission denied") + return + } + switch unit { + case "config": + switch id { + case "number": + valueInt64, ok := value.(int64) // 断言value为int64类型 + if !ok { + LOG.ERROR("[ERROR]:Value cannot be asserted to int64") + return + } + dm.Configs.Number[key] = valueInt64 // 使用断言后的int64值 + case "string": + valueStr, ok := value.(string) // 断言value为string类型 + if !ok { + LOG.ERROR("[ERROR]:Value cannot be asserted to string") + return + } + dm.Configs.String[key] = valueStr // 使用断言后的string值 + case "float": + valueFloat64, ok := value.(float64) // 断言value为float64类型 + if !ok { + LOG.ERROR("[ERROR]:Value cannot be asserted to float64") + return + } + dm.Configs.Float[key] = valueFloat64 // 使用断言后的float64值 + case "number_slice": + valueInt64Slice, ok := value.([]int64) // 断言value为[]int64类型 + if !ok { + LOG.ERROR("[ERROR]:Value cannot be asserted to []int64") + return + } + dm.Configs.Number_Slice[key] = valueInt64Slice // 使用断言后的[]int64值 + case "string_slice": + valueStrSlice, ok := value.([]string) // 断言value为[]string类型 + if !ok { + LOG.ERROR("[ERROR]:Value cannot be asserted to []string") + return + } + dm.Configs.String_Slice[key] = valueStrSlice // 使用断言后的[]string值 + case "hash": + valueStr, ok := value.(string) // 断言value为string类型 + if !ok { + LOG.ERROR("[ERROR]:Value cannot be asserted to string") + return + } + dm.Configs.Hash = valueStr // 使用断言后的string值 + default: + LOG.ERROR("[ERROR]:Invalid id %s", id) + } case "user": - user, ok := db.Users[id] + valueStr, ok := value.(string) // 断言value为string类型 + if !ok { + LOG.ERROR("[ERROR]:Value cannot be asserted to string") + return + } + user, ok := dm.Users[id] + if !ok { + dm.Users[id] = User{ + Id: id, + Data: make(map[string]string), + } + user = dm.Users[id] + } + if user.Data == nil { + user.Data = make(map[string]string) + } + user.Data[key] = valueStr // 使用断言后的string值 + case "group": + valueStr, ok := value.(string) // 断言value为string类型 + if !ok { + LOG.ERROR("[ERROR]:Value cannot be asserted to string") + return + } + group, ok := dm.Groups[id] + if !ok { + dm.Groups[id] = Group{ + Id: id, + Data: make(map[string]string), + } + group = dm.Groups[id] + } + if group.Data == nil { + group.Data = make(map[string]string) + } + group.Data[key] = valueStr // 使用断言后的string值 + case "global": + valueStr, ok := value.(string) // 断言value为string类型 + if !ok { + LOG.ERROR("[ERROR]:Value cannot be asserted to string") + return + } + global, ok := dm.Global[id] + if !ok { + dm.Global[id] = Global{ + Id: id, + Data: make(map[string]string), + } + global = dm.Global[id] + } + if global.Data == nil { + global.Data = make(map[string]string) + } + global.Data[key] = valueStr // 使用断言后的string值 + default: + LOG.ERROR("[ERROR]:Invalid unit %s", unit) + } +} + +func dataGet(datamap string, unit string, id string, key string, allowed bool) (interface{}, bool) { + dm, ok := DB.Datamaps[datamap] + if !ok { + LOG.WARN("[WARNING]:Datamap %s not found", datamap) + return "", false + } + if !allowed && dm.Permission != "private" { + LOG.WARN("[WARNING]:Permission denied") + return "", false + } + switch unit { + case "config": + switch id { + case "number": + value, ok := dm.Configs.Number[key] + if !ok { + LOG.WARN("[WARNING]:Config %s not found", key) + return 0, false + } + return value, true + case "string": + value, ok := dm.Configs.String[key] + if !ok { + LOG.WARN("[WARNING]:Config %s not found", key) + return "", false + } + return value, true + case "float": + value, ok := dm.Configs.Float[key] + if !ok { + LOG.WARN("[WARNING]:Config %s not found", key) + return 0.0, false + } + return value, true + case "number_slice": + value, ok := dm.Configs.Number_Slice[key] + if !ok { + LOG.WARN("[WARNING]:Config %s not found", key) + return []int64{}, false + } + return value, true + case "string_slice": + value, ok := dm.Configs.String_Slice[key] + if !ok { + LOG.WARN("[WARNING]:Config %s not found", key) + return []string{}, false + } + return value, true + case "hash": + return dm.Configs.Hash, true + default: + LOG.ERROR("[ERROR]:Invalid id %s", id) + return "", false + } + case "user": + user, ok := dm.Users[id] if !ok { LOG.WARN("[WARNING]:User %s not found", id) return "", false @@ -148,7 +397,7 @@ func dataGet(db *Database, category string, id string, key string) (string, bool } return value, true case "group": - group, ok := db.Groups[id] + group, ok := dm.Groups[id] if !ok { LOG.WARN("[WARNING]:Group %s not found", id) return "", false @@ -164,7 +413,7 @@ func dataGet(db *Database, category string, id string, key string) (string, bool } return value, true case "global": - global, ok := db.Global[id] + global, ok := dm.Global[id] if !ok { LOG.WARN("[WARNING]:Global %s not found", id) return "", false @@ -180,62 +429,15 @@ func dataGet(db *Database, category string, id string, key string) (string, bool } return value, true default: - LOG.ERROR("[ERROR]:Invalid category %s", category) + LOG.ERROR("[ERROR]:Invalid unit %s", unit) return "", false } } -func dataSet(db *Database, category string, id string, key string, value string) { - // 修改数据 - switch category { - case "user": - user, ok := db.Users[id] - if !ok { - db.Users[id] = User{ - Id: id, - Data: make(map[string]string), - } - user = db.Users[id] - } - if user.Data == nil { - user.Data = make(map[string]string) - } - user.Data[key] = value - case "group": - group, ok := db.Groups[id] - if !ok { - db.Groups[id] = Group{ - Id: id, - Data: make(map[string]string), - } - group = db.Groups[id] - } - if group.Data == nil { - group.Data = make(map[string]string) - } - group.Data[key] = value - case "global": - global, ok := db.Global[id] - if !ok { - db.Global[id] = Global{ - Id: id, - Data: make(map[string]string), - } - global = db.Global[id] - } - if global.Data == nil { - global.Data = make(map[string]string) - } - global.Data[key] = value - default: - LOG.ERROR("[ERROR]:Invalid category %s", category) - } -} - func initializeDatabase() *Database { // 启动并检查程序 LOG.INFO("Starting database ...") - db := newDatabase("datamap") + db := newDatabase() loadData(&db) LOG.INFO("Database started successfully.") return &db @@ -272,12 +474,67 @@ func Start() { select {} // 阻塞 } -func Get(category string, id string, key string) (string, bool) { - // 查询数据 - return dataGet(DB, category, id, key) +func CreatePublicDatamap(id string) { + // 创建公开数据表 + db := newDatamap(id) + db.Permission = "public" + DB.Datamaps[id] = db } -func Set(category string, id string, key string, value string) { - // 修改数据 - dataSet(DB, category, id, key, value) +func Get(app wba.AppInfo, datamap string, unit string, id string, key string, isGettingConfig bool) (interface{}, bool) { + // 查询数据 + if unit == "config" && id == "hash" { + // app不允许访问hash数据 + LOG.ERROR("[ERROR]:App %s is not allowed to access hash data", app.Name) + return "", false + } + if !isGettingConfig && unit == "config" { + // 不允许在非config数据表中访问config数据 + LOG.ERROR("[ERROR]:App %s is not allowed to access config data", app.Name) + return "", false + } + if app.Name != datamap { + // 需要master密码来访问其他app的数据 + hash := getCorePassword() + if hash == "" { + // 删除数据表哈希 + dataSet(app.Name, "config", "hash", "", "", false) + } + datahash, ok := dataGet(app.Name, "config", "hash", "", false) + if !ok { + LOG.ERROR("[ERROR]:Error while get hash of %s", app.Name) + } + if hash != datahash { + LOG.WARN("[WARNING]:App %s is not allowed to access data of %s", app.Name, datamap) + return dataGet(app.Name, unit, id, key, false) + } + + } + return dataGet(app.Name, unit, id, key, true) +} + +func Set(app wba.AppInfo, datamap string, unit string, id string, key string, value interface{}) { + // 修改数据 + if unit == "config" { + // app不允许修改config数据 + LOG.ERROR("[ERROR]:App %s is not allowed to modify config data", app.Name) + return + } + if app.Name != datamap { + // 需要master密码来访问其他app的数据 + hash := getCorePassword() + if hash == "" { + // 删除数据表哈希 + dataSet(app.Name, "config", "hash", "", "", false) + } + datahash, ok := dataGet(app.Name, "config", "hash", "", false) + if !ok { + LOG.ERROR("[ERROR]:Error while get hash of %s", app.Name) + } + if hash != datahash { + LOG.WARN("[WARNING]:App %s is not allowed to access data of %s", app.Name, datamap) + dataSet(app.Name, unit, id, key, value, false) + } + } + dataSet(app.Name, unit, id, key, value, true) } diff --git a/wba/wind.go b/wba/wind.go index 450fbb5..8c1022a 100644 --- a/wba/wind.go +++ b/wba/wind.go @@ -53,6 +53,16 @@ type WindAPI interface { Log(log string, args ...interface{}) } +type Database interface { + VarSet(app AppInfo, datamap string, unit string, id string, key string, value string) + VarGet(app AppInfo, datamap string, unit string, id string, key string) (string, bool) + GetIntConfig(app AppInfo, datamap string, key string) (int64, bool) + GetStringConfig(app AppInfo, datamap string, key string) (string, bool) + GetFloatConfig(app AppInfo, datamap string, key string) (float64, bool) + GetIntSliceConfig(app AppInfo, datamap string, key string) ([]int64, bool) + GetStringSliceConfig(app AppInfo, datamap string, key string) ([]string, bool) +} + type AppInfo struct { Name string Version string From bb599fad280e6217d1cd35edd10583783f6cfd12 Mon Sep 17 00:00:00 2001 From: Thun_Ann <2865813065@qq.com> Date: Tue, 25 Feb 2025 08:49:59 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=BA=93=E5=92=8C=E9=85=8D=E7=BD=AE=E9=A1=B9=E7=9A=84?= =?UTF-8?q?api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/api.go | 77 --------------- database/database.go | 227 +++++++++++++++++++++++++++++-------------- wba/wind.go | 114 ++++++++++++++++++++-- 3 files changed, 262 insertions(+), 156 deletions(-) diff --git a/core/api.go b/core/api.go index bc90cc3..2420bde 100644 --- a/core/api.go +++ b/core/api.go @@ -2,7 +2,6 @@ package core import ( "ProjectWIND/LOG" - "ProjectWIND/database" "ProjectWIND/wba" "crypto/rand" "fmt" @@ -821,82 +820,6 @@ func (a *apiInfo) Log(content string, args ...interface{}) { //database模块 //数据库部分允许字符串变量的读写操作,允许获取配置项操作 -func (a *apiInfo) VarSet(app wba.AppInfo, datamap string, unit string, id string, key string, value string) { - database.Set(app, datamap, unit, id, key, value) -} - -func (a *apiInfo) VarGet(app wba.AppInfo, datamap string, unit string, id string, key string) (string, bool) { - res, ok := database.Get(app, datamap, unit, id, key, false) - if !ok { - return "", false - } - resStr, ok := res.(string) - if !ok { - return "", false - } - return resStr, true -} - -func (a *apiInfo) GetIntConfig(app wba.AppInfo, datamap string, key string) (int64, bool) { - res, ok := database.Get(app, datamap, "config", "number", key, true) - if !ok { - return 0, false - } - resInt, ok := res.(int64) - if !ok { - return 0, false - } - return resInt, true -} - -func (a *apiInfo) GetStringConfig(app wba.AppInfo, datamap string, key string) (string, bool) { - res, ok := database.Get(app, datamap, "config", "string", key, true) - if !ok { - return "", false - } - resStr, ok := res.(string) - if !ok { - return "", false - } - return resStr, true -} - -func (a *apiInfo) GetFloatConfig(app wba.AppInfo, datamap string, key string) (float64, bool) { - res, ok := database.Get(app, datamap, "config", "float", key, true) - if !ok { - return 0, false - } - resFloat, ok := res.(float64) - if !ok { - return 0, false - } - return resFloat, true -} - -func (a *apiInfo) GetIntSliceConfig(app wba.AppInfo, datamap string, key string) ([]int64, bool) { - res, ok := database.Get(app, datamap, "config", "number_slice", key, true) - if !ok { - return nil, false - } - resSlice, ok := res.([]int64) - if !ok { - return nil, false - } - return resSlice, true -} - -func (a *apiInfo) GetStringSliceConfig(app wba.AppInfo, datamap string, key string) ([]string, bool) { - res, ok := database.Get(app, datamap, "config", "string_slice", key, true) - if !ok { - return nil, false - } - resSlice, ok := res.([]string) - if !ok { - return nil, false - } - return resSlice, true -} - // 文件管理模块 //TODO: 文件管理模块待实现 diff --git a/database/database.go b/database/database.go index 01544f9..468cee8 100644 --- a/database/database.go +++ b/database/database.go @@ -2,7 +2,6 @@ package database import ( "ProjectWIND/LOG" - "ProjectWIND/wba" "encoding/json" "errors" "os" @@ -83,7 +82,7 @@ func (this *Database) addDatamap(id string) { // func hash(word string) string { // hash, err := bcrypt.GenerateFromPassword([]byte(word), bcrypt.DefaultCost) // if err != nil { -// LOG.ERROR("[ERROR]Error while hash password: %v", err) +// LOG.Error("[Error]Error while hash password: %v", err) // return "" // } // return string(hash) @@ -98,7 +97,7 @@ func folderCheck(filename string) { if _, err := os.Stat(filename); os.IsNotExist(err) { err := os.MkdirAll(filename, 0755) if err != nil { - LOG.FATAL("[ERROR]Error occured while create folder: %v", err) + LOG.Fatal("[Error]Error occured while create folder: %v", err) } } } @@ -110,12 +109,12 @@ func fileCheck(filename string) { if _, err := os.Stat(filename); os.IsNotExist(err) { file, err := os.Create(filename) if err != nil { - LOG.FATAL("[ERROR]Error occured while create file: %v", err) + LOG.Fatal("[Error]Error occured while create file: %v", err) } defer func(file *os.File) { err := file.Close() if err != nil { - LOG.FATAL("[ERROR]Error occured while close file: %v", err) + LOG.Fatal("[Error]Error occured while close file: %v", err) } }(file) } @@ -124,13 +123,13 @@ func fileCheck(filename string) { func writeContent(f *os.File, str string) error { // 写入内容到文件 if f == nil { - // log.Printf("[ERROR]file is nil") - LOG.ERROR("[ERROR]file is nil") + // log.Printf("[Error]file is nil") + LOG.Error("[Error]file is nil") return errors.New("file is nil") } _, err := f.Write([]byte(str)) if err != nil { - LOG.ERROR("[ERROR]Error while write content to file: %v", err) + LOG.Error("[Error]Error while write content to file: %v", err) return err } return nil @@ -152,18 +151,18 @@ func getCorePassword() string { fileCheck(filename) dataJson, err := printContent(filename) if err != nil { - LOG.ERROR("[WARNING]Error while read file %s: %v") + LOG.Error("[Error]Error while read file %s: %v", filename, err) return "" } config := make(map[string]string) err = json.Unmarshal([]byte(dataJson), config) if err != nil { - LOG.WARN("[WARNING]Error while unmarshal data: %v", err) + LOG.Error("[Error]Error while unmarshal data: %v", err) return "" } password, ok := config["password"] if !ok { - LOG.WARN("[WARNING]Password not found in core.json") + LOG.Warn("[Warning]Password not found in core.json") return "" } return password @@ -173,13 +172,13 @@ func saveData(db *Database) error { // 保存数据到文件 dataJson, err := json.Marshal(db) if err != nil { - LOG.ERROR("[ERROR]:Error while marshal data: %v", err) + LOG.Error("[Error]:Error while marshal data: %v", err) return err } filename := address file, err := os.Create(filename) if err != nil { - LOG.ERROR("[ERROR]:Error while create file %s: %v", filename, err) + LOG.Error("[Error]:Error while create file %s: %v", filename, err) return err } writeContent(file, string(dataJson)) @@ -192,14 +191,14 @@ func loadData(db *Database) error { fileCheck(filename) dataJson, err := printContent(filename) if err != nil { - // log.Printf("[ERROR]:Error while read file %s: %v", filename, err) - LOG.ERROR("[ERROR]:Error while read file %s: %v", filename, err) + // log.Printf("[Error]:Error while read file %s: %v", filename, err) + LOG.Error("[Error]:Error while read file %s: %v", filename, err) return err } err = json.Unmarshal([]byte(dataJson), db) if err != nil { - // log.Printf("[ERROR]:Error while unmarshal data: %v", err) - LOG.WARN("[WARNING]:Error while unmarshal data: %v", err) + // log.Printf("[Error]:Error while unmarshal data: %v", err) + LOG.Warn("[Warning]:Error while unmarshal data: %v", err) return err } return nil @@ -212,11 +211,11 @@ func dataSet(datamap string, unit string, id string, key string, value interface dm, ok := DB.Datamaps[datamap] if !ok { // 创建新数据表 - DB.Datamaps[datamap] = newDatamap(datamap) + DB.addDatamap(datamap) dm = DB.Datamaps[datamap] } if !allowed && dm.Permission != "private" { - LOG.WARN("[WARNING]:Permission denied") + LOG.Warn("[Warning]:Permission denied") return } switch unit { @@ -225,52 +224,52 @@ func dataSet(datamap string, unit string, id string, key string, value interface case "number": valueInt64, ok := value.(int64) // 断言value为int64类型 if !ok { - LOG.ERROR("[ERROR]:Value cannot be asserted to int64") + LOG.Error("[Error]:Value cannot be asserted to int64") return } dm.Configs.Number[key] = valueInt64 // 使用断言后的int64值 case "string": valueStr, ok := value.(string) // 断言value为string类型 if !ok { - LOG.ERROR("[ERROR]:Value cannot be asserted to string") + LOG.Error("[Error]:Value cannot be asserted to string") return } dm.Configs.String[key] = valueStr // 使用断言后的string值 case "float": valueFloat64, ok := value.(float64) // 断言value为float64类型 if !ok { - LOG.ERROR("[ERROR]:Value cannot be asserted to float64") + LOG.Error("[Error]:Value cannot be asserted to float64") return } dm.Configs.Float[key] = valueFloat64 // 使用断言后的float64值 case "number_slice": valueInt64Slice, ok := value.([]int64) // 断言value为[]int64类型 if !ok { - LOG.ERROR("[ERROR]:Value cannot be asserted to []int64") + LOG.Error("[Error]:Value cannot be asserted to []int64") return } dm.Configs.Number_Slice[key] = valueInt64Slice // 使用断言后的[]int64值 case "string_slice": valueStrSlice, ok := value.([]string) // 断言value为[]string类型 if !ok { - LOG.ERROR("[ERROR]:Value cannot be asserted to []string") + LOG.Error("[Error]:Value cannot be asserted to []string") return } dm.Configs.String_Slice[key] = valueStrSlice // 使用断言后的[]string值 case "hash": valueStr, ok := value.(string) // 断言value为string类型 if !ok { - LOG.ERROR("[ERROR]:Value cannot be asserted to string") + LOG.Error("[Error]:Value cannot be asserted to string") return } dm.Configs.Hash = valueStr // 使用断言后的string值 default: - LOG.ERROR("[ERROR]:Invalid id %s", id) + LOG.Error("[Error]:Invalid id %s", id) } case "user": valueStr, ok := value.(string) // 断言value为string类型 if !ok { - LOG.ERROR("[ERROR]:Value cannot be asserted to string") + LOG.Error("[Error]:Value cannot be asserted to string") return } user, ok := dm.Users[id] @@ -288,7 +287,7 @@ func dataSet(datamap string, unit string, id string, key string, value interface case "group": valueStr, ok := value.(string) // 断言value为string类型 if !ok { - LOG.ERROR("[ERROR]:Value cannot be asserted to string") + LOG.Error("[Error]:Value cannot be asserted to string") return } group, ok := dm.Groups[id] @@ -306,7 +305,7 @@ func dataSet(datamap string, unit string, id string, key string, value interface case "global": valueStr, ok := value.(string) // 断言value为string类型 if !ok { - LOG.ERROR("[ERROR]:Value cannot be asserted to string") + LOG.Error("[Error]:Value cannot be asserted to string") return } global, ok := dm.Global[id] @@ -322,18 +321,18 @@ func dataSet(datamap string, unit string, id string, key string, value interface } global.Data[key] = valueStr // 使用断言后的string值 default: - LOG.ERROR("[ERROR]:Invalid unit %s", unit) + LOG.Error("[Error]:Invalid unit %s", unit) } } func dataGet(datamap string, unit string, id string, key string, allowed bool) (interface{}, bool) { dm, ok := DB.Datamaps[datamap] if !ok { - LOG.WARN("[WARNING]:Datamap %s not found", datamap) + LOG.Warn("[Warning]:Datamap %s not found", datamap) return "", false } if !allowed && dm.Permission != "private" { - LOG.WARN("[WARNING]:Permission denied") + LOG.Warn("[Warning]:Permission denied") return "", false } switch unit { @@ -342,104 +341,104 @@ func dataGet(datamap string, unit string, id string, key string, allowed bool) ( case "number": value, ok := dm.Configs.Number[key] if !ok { - LOG.WARN("[WARNING]:Config %s not found", key) + LOG.Warn("[Warning]:Config %s not found", key) return 0, false } return value, true case "string": value, ok := dm.Configs.String[key] if !ok { - LOG.WARN("[WARNING]:Config %s not found", key) + LOG.Warn("[Warning]:Config %s not found", key) return "", false } return value, true case "float": value, ok := dm.Configs.Float[key] if !ok { - LOG.WARN("[WARNING]:Config %s not found", key) + LOG.Warn("[Warning]:Config %s not found", key) return 0.0, false } return value, true case "number_slice": value, ok := dm.Configs.Number_Slice[key] if !ok { - LOG.WARN("[WARNING]:Config %s not found", key) + LOG.Warn("[Warning]:Config %s not found", key) return []int64{}, false } return value, true case "string_slice": value, ok := dm.Configs.String_Slice[key] if !ok { - LOG.WARN("[WARNING]:Config %s not found", key) + LOG.Warn("[Warning]:Config %s not found", key) return []string{}, false } return value, true case "hash": return dm.Configs.Hash, true default: - LOG.ERROR("[ERROR]:Invalid id %s", id) + LOG.Error("[Error]:Invalid id %s", id) return "", false } case "user": user, ok := dm.Users[id] if !ok { - LOG.WARN("[WARNING]:User %s not found", id) + LOG.Warn("[Warning]:User %s not found", id) return "", false } if user.Data == nil { - LOG.WARN("[WARNING]:User %s's data is nil", id) + LOG.Warn("[Warning]:User %s's data is nil", id) return "", false } value, ok := user.Data[key] if !ok { - LOG.WARN("[WARNING]:User %s's data %s not found", id, key) + LOG.Warn("[Warning]:User %s's data %s not found", id, key) return "", false } return value, true case "group": group, ok := dm.Groups[id] if !ok { - LOG.WARN("[WARNING]:Group %s not found", id) + LOG.Warn("[Warning]:Group %s not found", id) return "", false } if group.Data == nil { - LOG.WARN("[WARNING]:Group %s's data is nil", id) + LOG.Warn("[Warning]:Group %s's data is nil", id) return "", false } value, ok := group.Data[key] if !ok { - LOG.WARN("[WARNING]:Group %s's data %s not found", id, key) + LOG.Warn("[Warning]:Group %s's data %s not found", id, key) return "", false } return value, true case "global": global, ok := dm.Global[id] if !ok { - LOG.WARN("[WARNING]:Global %s not found", id) + LOG.Warn("[Warning]:Global %s not found", id) return "", false } if global.Data == nil { - LOG.WARN("[WARNING]:Global data of %s is nil", id) + LOG.Warn("[Warning]:Global data of %s is nil", id) return "", false } value, ok := global.Data[key] if !ok { - LOG.WARN("[WARNING]:Global data of %s's %s not found", id, key) + LOG.Warn("[Warning]:Global data of %s's %s not found", id, key) return "", false } return value, true default: - LOG.ERROR("[ERROR]:Invalid category %s", category) + LOG.Error("[Error]:Invalid unit %s", unit) return "", false } } func initializeDatabase() *Database { // 启动并检查程序 - LOG.INFO("Starting database ...") + LOG.Info("Starting database ...") db := newDatabase() loadData(&db) - LOG.INFO("Database started successfully.") + LOG.Info("Database started successfully.") return &db } @@ -460,12 +459,12 @@ func Start() { select { case <-dataChan: // 接收到信号,保存数据并退出程序 - LOG.INFO("Received signal, saving data and exiting...") + LOG.Info("Received signal, saving data and exiting...") saveData(DB) os.Exit(0) case <-saveTicker.C: // 定时保存数据 - LOG.INFO("Saving data automatically...") + LOG.Info("Saving data automatically...") saveData(DB) } } @@ -481,60 +480,146 @@ func CreatePublicDatamap(id string) { DB.Datamaps[id] = db } -func Get(app wba.AppInfo, datamap string, unit string, id string, key string, isGettingConfig bool) (interface{}, bool) { +func Get(appName string, datamap string, unit string, id string, key string, isGettingConfig bool) (interface{}, bool) { // 查询数据 if unit == "config" && id == "hash" { // app不允许访问hash数据 - LOG.ERROR("[ERROR]:App %s is not allowed to access hash data", app.Name) + LOG.Error("[Error]:App %s is not allowed to access hash data", appName) return "", false } if !isGettingConfig && unit == "config" { // 不允许在非config数据表中访问config数据 - LOG.ERROR("[ERROR]:App %s is not allowed to access config data", app.Name) + LOG.Error("[Error]:App %s is not allowed to access config data", appName) return "", false } - if app.Name != datamap { + if appName != datamap { // 需要master密码来访问其他app的数据 hash := getCorePassword() if hash == "" { // 删除数据表哈希 - dataSet(app.Name, "config", "hash", "", "", false) + dataSet(appName, "config", "hash", "", "", false) } - datahash, ok := dataGet(app.Name, "config", "hash", "", false) + datahash, ok := dataGet(appName, "config", "hash", "", false) if !ok { - LOG.ERROR("[ERROR]:Error while get hash of %s", app.Name) + LOG.Error("[Error]:Error while get hash of %s", appName) } if hash != datahash { - LOG.WARN("[WARNING]:App %s is not allowed to access data of %s", app.Name, datamap) - return dataGet(app.Name, unit, id, key, false) + LOG.Warn("[Warning]:App %s is not allowed to access data of %s", appName, datamap) + return dataGet(appName, unit, id, key, false) } } - return dataGet(app.Name, unit, id, key, true) + return dataGet(appName, unit, id, key, true) } -func Set(app wba.AppInfo, datamap string, unit string, id string, key string, value interface{}) { +func Set(appName string, datamap string, unit string, id string, key string, value interface{}) { // 修改数据 if unit == "config" { // app不允许修改config数据 - LOG.ERROR("[ERROR]:App %s is not allowed to modify config data", app.Name) + LOG.Error("[Error]:App %s is not allowed to modify config data", appName) return } - if app.Name != datamap { + if appName != datamap { // 需要master密码来访问其他app的数据 hash := getCorePassword() if hash == "" { // 删除数据表哈希 - dataSet(app.Name, "config", "hash", "", "", false) + dataSet(appName, "config", "hash", "", "", false) } - datahash, ok := dataGet(app.Name, "config", "hash", "", false) + datahash, ok := dataGet(appName, "config", "hash", "", false) if !ok { - LOG.ERROR("[ERROR]:Error while get hash of %s", app.Name) + LOG.Error("[Error]:Error while get hash of %s", appName) } if hash != datahash { - LOG.WARN("[WARNING]:App %s is not allowed to access data of %s", app.Name, datamap) - dataSet(app.Name, unit, id, key, value, false) + LOG.Warn("[Warning]:App %s is not allowed to access data of %s", appName, datamap) + dataSet(appName, unit, id, key, value, false) } } - dataSet(app.Name, unit, id, key, value, true) + dataSet(appName, unit, id, key, value, true) } + +type DatabaseHandlerImpl struct{} + +func (dbh *DatabaseHandlerImpl) Set(appName string, datamap string, unit string, id string, key string, value interface{}) { + Set(appName, datamap, unit, id, key, value) +} + +func (dbh *DatabaseHandlerImpl) Get(appName string, datamap string, unit string, id string, key string, isGettingConfig bool) (interface{}, bool) { + return Get(appName, datamap, unit, id, key, isGettingConfig) +} + +// func VarSet(app wba.AppInfo, datamap string, unit string, id string, key string, value string) { +// Set(app.Name, datamap, unit, id, key, value) +// } + +// func VarGet(app wba.AppInfo, datamap string, unit string, id string, key string) (string, bool) { +// res, ok := Get(app.Name, datamap, unit, id, key, false) +// if !ok { +// return "", false +// } +// resStr, ok := res.(string) +// if !ok { +// return "", false +// } +// return resStr, true +// } + +// func GetIntConfig(app wba.AppInfo, datamap string, key string) (int64, bool) { +// res, ok := Get(app.Name, datamap, "config", "number", key, true) +// if !ok { +// return 0, false +// } +// resInt, ok := res.(int64) +// if !ok { +// return 0, false +// } +// return resInt, true +// } + +// func GetStringConfig(app wba.AppInfo, datamap string, key string) (string, bool) { +// res, ok := Get(app.Name, datamap, "config", "string", key, true) +// if !ok { +// return "", false +// } +// resStr, ok := res.(string) +// if !ok { +// return "", false +// } +// return resStr, true +// } + +// func GetFloatConfig(app wba.AppInfo, datamap string, key string) (float64, bool) { +// res, ok := Get(app.Name, datamap, "config", "float", key, true) +// if !ok { +// return 0, false +// } +// resFloat, ok := res.(float64) +// if !ok { +// return 0, false +// } +// return resFloat, true +// } + +// func GetIntSliceConfig(app wba.AppInfo, datamap string, key string) ([]int64, bool) { +// res, ok := Get(app.Name, datamap, "config", "number_slice", key, true) +// if !ok { +// return nil, false +// } +// resSlice, ok := res.([]int64) +// if !ok { +// return nil, false +// } +// return resSlice, true +// } + +// func GetStringSliceConfig(app wba.AppInfo, datamap string, key string) ([]string, bool) { +// res, ok := Get(app.Name, datamap, "config", "string_slice", key, true) +// if !ok { +// return nil, false +// } +// resSlice, ok := res.([]string) +// if !ok { +// return nil, false +// } +// return resSlice, true +// } diff --git a/wba/wind.go b/wba/wind.go index c2666b1..8bcb5e9 100644 --- a/wba/wind.go +++ b/wba/wind.go @@ -265,14 +265,9 @@ type WindStandardProtocolAPI interface { Log(log string, args ...interface{}) } -type Database interface { - VarSet(app AppInfo, datamap string, unit string, id string, key string, value string) - VarGet(app AppInfo, datamap string, unit string, id string, key string) (string, bool) - GetIntConfig(app AppInfo, datamap string, key string) (int64, bool) - GetStringConfig(app AppInfo, datamap string, key string) (string, bool) - GetFloatConfig(app AppInfo, datamap string, key string) (float64, bool) - GetIntSliceConfig(app AppInfo, datamap string, key string) ([]int64, bool) - GetStringSliceConfig(app AppInfo, datamap string, key string) ([]string, bool) +type DataBaseHandler interface { + Set(appName string, datamap string, unit string, id string, key string, value interface{}) + Get(appName string, datamap string, unit string, id string, key string, isGettingConfig bool) (interface{}, bool) } type AppInfo struct { @@ -292,6 +287,7 @@ type AppInfo struct { MetaEventHandler func(msg MetaEventInfo) ScheduledTasks map[string]ScheduledTaskInfo API map[string]interface{} + dbHandler DataBaseHandler } func (ai AppInfo) Get() AppInfo { @@ -311,6 +307,108 @@ func (ai *AppInfo) AddNoticeEventHandler(ScheduledTask ScheduledTaskInfo) { ai.ScheduledTasks[ScheduledTask.Name] = ScheduledTask } +func (ai *AppInfo) VarSet(datamap string, unit string, id string, key string, value string) { + if ai.dbHandler != nil { + ai.dbHandler.Set(ai.Name, datamap, unit, id, key, value) + } +} + +// VarGet 获取变量 +func (ai *AppInfo) VarGet(datamap string, unit string, id string, key string) (string, bool) { + if ai.dbHandler != nil { + res, ok := ai.dbHandler.Get(ai.Name, datamap, unit, id, key, false) + if !ok { + return "", false + } + resStr, ok := res.(string) + if !ok { + return "", false + } + return resStr, true + } + return "", false +} + +// GetIntConfig 获取整数配置 +func (ai *AppInfo) GetIntConfig(datamap string, key string) (int64, bool) { + if ai.dbHandler != nil { + res, ok := ai.dbHandler.Get(ai.Name, datamap, "config", "number", key, true) + if !ok { + return 0, false + } + resInt, ok := res.(int64) + if !ok { + return 0, false + } + return resInt, true + } + return 0, false +} + +// GetStringConfig 获取字符串配置 +func (ai *AppInfo) GetStringConfig(datamap string, key string) (string, bool) { + if ai.dbHandler != nil { + res, ok := ai.dbHandler.Get(ai.Name, datamap, "config", "string", key, true) + if !ok { + return "", false + } + resStr, ok := res.(string) + if !ok { + return "", false + } + return resStr, true + } + return "", false +} + +// GetFloatConfig 获取浮点数配置 +func (ai *AppInfo) GetFloatConfig(datamap string, key string) (float64, bool) { + if ai.dbHandler != nil { + res, ok := ai.dbHandler.Get(ai.Name, datamap, "config", "float", key, true) + if !ok { + return 0, false + } + resFloat, ok := res.(float64) + if !ok { + return 0, false + } + return resFloat, true + } + return 0, false +} + +// GetIntSliceConfig 获取整数切片配置 +func (ai *AppInfo) GetIntSliceConfig(datamap string, key string) ([]int64, bool) { + if ai.dbHandler != nil { + res, ok := ai.dbHandler.Get(ai.Name, datamap, "config", "number_slice", key, true) + if !ok { + return nil, false + } + resSlice, ok := res.([]int64) + if !ok { + return nil, false + } + return resSlice, true + } + return nil, false +} + +// GetStringSliceConfig 获取字符串切片配置 +func (ai *AppInfo) GetStringSliceConfig(datamap string, key string) ([]string, bool) { + if ai.dbHandler != nil { + res, ok := ai.dbHandler.Get(ai.Name, datamap, "config", "string_slice", key, true) + if !ok { + return nil, false + } + resSlice, ok := res.([]string) + if !ok { + return nil, false + } + return resSlice, true + } + return nil, false +} + type AppInfoOption func(ei *AppInfo) func WithName(name string) AppInfoOption {