apimain.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. package main
  2. import (
  3. "Gwen/config"
  4. "Gwen/global"
  5. "Gwen/http"
  6. "Gwen/lib/cache"
  7. "Gwen/lib/lock"
  8. "Gwen/lib/logger"
  9. "Gwen/lib/orm"
  10. "Gwen/lib/upload"
  11. "Gwen/model"
  12. "Gwen/service"
  13. "fmt"
  14. "github.com/BurntSushi/toml"
  15. "github.com/gin-gonic/gin"
  16. "github.com/go-playground/locales/en"
  17. "github.com/go-playground/locales/zh_Hans_CN"
  18. ut "github.com/go-playground/universal-translator"
  19. "github.com/go-playground/validator/v10"
  20. en_translations "github.com/go-playground/validator/v10/translations/en"
  21. zh_translations "github.com/go-playground/validator/v10/translations/zh"
  22. "github.com/go-redis/redis/v8"
  23. "github.com/nicksnyder/go-i18n/v2/i18n"
  24. "golang.org/x/text/language"
  25. nethttp "net/http"
  26. "reflect"
  27. )
  28. // @title 管理系统API
  29. // @version 1.0
  30. // @description 接口
  31. // @basePath /api
  32. // @securityDefinitions.apikey token
  33. // @in header
  34. // @name api-token
  35. // @securitydefinitions.apikey BearerAuth
  36. // @in header
  37. // @name Authorization
  38. func main() {
  39. //配置解析
  40. global.Viper = config.Init(&global.Config)
  41. //日志
  42. global.Logger = logger.New(&logger.Config{
  43. Path: global.Config.Logger.Path,
  44. Level: global.Config.Logger.Level,
  45. ReportCaller: global.Config.Logger.ReportCaller,
  46. })
  47. InitI18n()
  48. //redis
  49. global.Redis = redis.NewClient(&redis.Options{
  50. Addr: global.Config.Redis.Addr,
  51. Password: global.Config.Redis.Password,
  52. DB: global.Config.Redis.Db,
  53. })
  54. //cache
  55. if global.Config.Cache.Type == cache.TypeFile {
  56. fc := cache.NewFileCache()
  57. fc.SetDir(global.Config.Cache.FileDir)
  58. global.Cache = fc
  59. } else if global.Config.Cache.Type == cache.TypeRedis {
  60. global.Cache = cache.NewRedis(&redis.Options{
  61. Addr: global.Config.Cache.RedisAddr,
  62. Password: global.Config.Cache.RedisPwd,
  63. DB: global.Config.Cache.RedisDb,
  64. })
  65. }
  66. //gorm
  67. if global.Config.Gorm.Type == config.TypeMysql {
  68. dns := global.Config.Mysql.Username + ":" + global.Config.Mysql.Password + "@(" + global.Config.Mysql.Addr + ")/" + global.Config.Mysql.Dbname + "?charset=utf8mb4&parseTime=True&loc=Local"
  69. global.DB = orm.NewMysql(&orm.MysqlConfig{
  70. Dns: dns,
  71. MaxIdleConns: global.Config.Gorm.MaxIdleConns,
  72. MaxOpenConns: global.Config.Gorm.MaxOpenConns,
  73. })
  74. } else {
  75. //sqlite
  76. global.DB = orm.NewSqlite(&orm.SqliteConfig{
  77. MaxIdleConns: global.Config.Gorm.MaxIdleConns,
  78. MaxOpenConns: global.Config.Gorm.MaxOpenConns,
  79. })
  80. }
  81. DatabaseAutoUpdate()
  82. //validator
  83. ApiInitValidator()
  84. //oss
  85. global.Oss = &upload.Oss{
  86. AccessKeyId: global.Config.Oss.AccessKeyId,
  87. AccessKeySecret: global.Config.Oss.AccessKeySecret,
  88. Host: global.Config.Oss.Host,
  89. CallbackUrl: global.Config.Oss.CallbackUrl,
  90. ExpireTime: global.Config.Oss.ExpireTime,
  91. MaxByte: global.Config.Oss.MaxByte,
  92. }
  93. //jwt
  94. //fmt.Println(global.Config.Jwt.PrivateKey)
  95. //global.Jwt = jwt.NewJwt(global.Config.Jwt.PrivateKey, global.Config.Jwt.ExpireDuration*time.Second)
  96. //locker
  97. global.Lock = lock.NewLocal()
  98. //gin
  99. http.ApiInit()
  100. }
  101. func ApiInitValidator() {
  102. validate := validator.New()
  103. // 定义不同的语言翻译
  104. enT := en.New()
  105. cn := zh_Hans_CN.New()
  106. uni := ut.New(enT, cn)
  107. enTrans, _ := uni.GetTranslator("en")
  108. zhTrans, _ := uni.GetTranslator("zh_Hans_CN")
  109. err := zh_translations.RegisterDefaultTranslations(validate, zhTrans)
  110. if err != nil {
  111. panic(err)
  112. }
  113. err = en_translations.RegisterDefaultTranslations(validate, enTrans)
  114. if err != nil {
  115. panic(err)
  116. }
  117. validate.RegisterTagNameFunc(func(field reflect.StructField) string {
  118. label := field.Tag.Get("label")
  119. if label == "" {
  120. return field.Name
  121. }
  122. return label
  123. })
  124. global.Validator.Validate = validate
  125. global.Validator.UT = uni // 存储 Universal Translator
  126. global.Validator.VTrans = zhTrans
  127. global.Validator.ValidStruct = func(ctx *gin.Context, i interface{}) []string {
  128. err := global.Validator.Validate.Struct(i)
  129. lang := ctx.GetHeader("Accept-Language")
  130. if lang == "" {
  131. lang = global.Config.Lang
  132. }
  133. trans := getTranslatorForLang(lang)
  134. errList := make([]string, 0, 10)
  135. if err != nil {
  136. if _, ok := err.(*validator.InvalidValidationError); ok {
  137. errList = append(errList, err.Error())
  138. return errList
  139. }
  140. for _, err2 := range err.(validator.ValidationErrors) {
  141. errList = append(errList, err2.Translate(trans))
  142. }
  143. }
  144. return errList
  145. }
  146. global.Validator.ValidVar = func(ctx *gin.Context, field interface{}, tag string) []string {
  147. err := global.Validator.Validate.Var(field, tag)
  148. lang := ctx.GetHeader("Accept-Language")
  149. if lang == "" {
  150. lang = global.Config.Lang
  151. }
  152. trans := getTranslatorForLang(lang)
  153. errList := make([]string, 0, 10)
  154. if err != nil {
  155. if _, ok := err.(*validator.InvalidValidationError); ok {
  156. errList = append(errList, err.Error())
  157. return errList
  158. }
  159. for _, err2 := range err.(validator.ValidationErrors) {
  160. errList = append(errList, err2.Translate(trans))
  161. }
  162. }
  163. return errList
  164. }
  165. }
  166. func getTranslatorForLang(lang string) ut.Translator {
  167. switch lang {
  168. case "zh_CN":
  169. fallthrough
  170. case "zh-CN":
  171. fallthrough
  172. case "zh":
  173. trans, _ := global.Validator.UT.GetTranslator("zh_Hans_CN")
  174. return trans
  175. case "en":
  176. fallthrough
  177. default:
  178. trans, _ := global.Validator.UT.GetTranslator("en")
  179. return trans
  180. }
  181. }
  182. func DatabaseAutoUpdate() {
  183. version := 220
  184. db := global.DB
  185. if global.Config.Gorm.Type == config.TypeMysql {
  186. //检查存不存在数据库,不存在则创建
  187. dbName := db.Migrator().CurrentDatabase()
  188. fmt.Println("dbName", dbName)
  189. if dbName == "" {
  190. dbName = global.Config.Mysql.Dbname
  191. // 移除 DSN 中的数据库名称,以便初始连接时不指定数据库
  192. dsnWithoutDB := global.Config.Mysql.Username + ":" + global.Config.Mysql.Password + "@(" + global.Config.Mysql.Addr + ")/?charset=utf8mb4&parseTime=True&loc=Local"
  193. //新链接
  194. dbWithoutDB := orm.NewMysql(&orm.MysqlConfig{
  195. Dns: dsnWithoutDB,
  196. })
  197. // 获取底层的 *sql.DB 对象,并确保在程序退出时关闭连接
  198. sqlDBWithoutDB, err := dbWithoutDB.DB()
  199. if err != nil {
  200. fmt.Printf("获取底层 *sql.DB 对象失败: %v\n", err)
  201. return
  202. }
  203. defer func() {
  204. if err := sqlDBWithoutDB.Close(); err != nil {
  205. fmt.Printf("关闭连接失败: %v\n", err)
  206. }
  207. }()
  208. err = dbWithoutDB.Exec("CREATE DATABASE IF NOT EXISTS " + dbName + " DEFAULT CHARSET utf8mb4").Error
  209. if err != nil {
  210. fmt.Println(err)
  211. return
  212. }
  213. }
  214. }
  215. if !db.Migrator().HasTable(&model.Version{}) {
  216. Migrate(uint(version))
  217. } else {
  218. //查找最后一个version
  219. var v model.Version
  220. db.Last(&v)
  221. if v.Version < uint(version) {
  222. Migrate(uint(version))
  223. }
  224. }
  225. }
  226. func Migrate(version uint) {
  227. fmt.Println("migrating....", version)
  228. err := global.DB.AutoMigrate(
  229. &model.Version{},
  230. &model.User{},
  231. &model.UserToken{},
  232. &model.Tag{},
  233. &model.AddressBook{},
  234. &model.Peer{},
  235. &model.Group{},
  236. &model.UserThird{},
  237. &model.Oauth{},
  238. &model.LoginLog{},
  239. &model.ShareRecord{},
  240. )
  241. if err != nil {
  242. fmt.Println("migrate err :=>", err)
  243. }
  244. global.DB.Create(&model.Version{Version: version})
  245. //如果是初次则创建一个默认用户
  246. var vc int64
  247. global.DB.Model(&model.Version{}).Count(&vc)
  248. if vc == 1 {
  249. localizer := global.Localizer(&gin.Context{
  250. Request: &nethttp.Request{},
  251. })
  252. defaultGroup, _ := localizer.LocalizeMessage(&i18n.Message{
  253. ID: "DefaultGroup",
  254. })
  255. group := &model.Group{
  256. Name: defaultGroup,
  257. Type: model.GroupTypeDefault,
  258. }
  259. service.AllService.GroupService.Create(group)
  260. shareGroup, _ := localizer.LocalizeMessage(&i18n.Message{
  261. ID: "ShareGroup",
  262. })
  263. groupShare := &model.Group{
  264. Name: shareGroup,
  265. Type: model.GroupTypeShare,
  266. }
  267. service.AllService.GroupService.Create(groupShare)
  268. //是true
  269. is_admin := true
  270. admin := &model.User{
  271. Username: "admin",
  272. Nickname: "Admin",
  273. Status: model.COMMON_STATUS_ENABLE,
  274. IsAdmin: &is_admin,
  275. GroupId: 1,
  276. }
  277. admin.Password = service.AllService.UserService.EncryptPassword("admin")
  278. global.DB.Create(admin)
  279. }
  280. }
  281. func InitI18n() {
  282. bundle := i18n.NewBundle(language.English)
  283. bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
  284. bundle.LoadMessageFile(global.Config.Gin.ResourcesPath + "/i18n/en.toml")
  285. bundle.LoadMessageFile(global.Config.Gin.ResourcesPath + "/i18n/zh_CN.toml")
  286. global.Localizer = func(ctx *gin.Context) *i18n.Localizer {
  287. lang := ctx.GetHeader("Accept-Language")
  288. if lang == "" {
  289. lang = global.Config.Lang
  290. }
  291. if lang == "en" {
  292. return i18n.NewLocalizer(bundle, "en")
  293. } else {
  294. return i18n.NewLocalizer(bundle, lang, "en")
  295. }
  296. }
  297. //personUnreadEmails := localizer.MustLocalize(&i18n.LocalizeConfig{
  298. // DefaultMessage: &i18n.Message{
  299. // ID: "PersonUnreadEmails",
  300. // },
  301. // PluralCount: 6,
  302. // TemplateData: map[string]interface{}{
  303. // "Name": "LE",
  304. // "PluralCount": 6,
  305. // },
  306. //})
  307. //personUnreadEmails, err := global.Localizer.LocalizeMessage(&i18n.Message{
  308. // ID: "ParamsError",
  309. //})
  310. //fmt.Println(err, personUnreadEmails)
  311. }