diff --git a/go_fabric/.idea/.gitignore b/go_fabric/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/go_fabric/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/go_fabric/.idea/go_fabric.iml b/go_fabric/.idea/go_fabric.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/go_fabric/.idea/go_fabric.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/go_fabric/.idea/modules.xml b/go_fabric/.idea/modules.xml new file mode 100644 index 0000000..74a6653 --- /dev/null +++ b/go_fabric/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/go_fabric/.idea/vcs.xml b/go_fabric/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/go_fabric/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/go_fabric/api/v1/common.go b/go_fabric/api/v1/common.go new file mode 100644 index 0000000..e93ddc3 --- /dev/null +++ b/go_fabric/api/v1/common.go @@ -0,0 +1,21 @@ +package v1 + +import ( + "encoding/json" + "go_fabric/serializer" +) + +func ErrorResponse(err error) serializer.Response { + if _, ok := err.(*json.UnmarshalTypeError); ok { + return serializer.Response{ + Status: 400, + Msg: "JSON类型不匹配", + Error: err.Error(), + } + } + return serializer.Response{ + Status: 400, + Msg: "参数错误", + Error: err.Error(), + } +} diff --git a/go_fabric/api/v1/poem.go b/go_fabric/api/v1/poem.go new file mode 100644 index 0000000..5cbf3a7 --- /dev/null +++ b/go_fabric/api/v1/poem.go @@ -0,0 +1,20 @@ +package v1 + +import ( + "go_fabric/pkg/util" + "go_fabric/service" + "net/http" + + "github.com/gin-gonic/gin" +) + +func PoemGet(c *gin.Context) { + var userRegister service.UserService + if err := c.ShouldBind(&userRegister); err == nil { + res := userRegister.Register(c.Request.Context()) + c.JSON(http.StatusOK, res) + } else { + c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误 + util.LoggerObj.Error(err) + } +} diff --git a/go_fabric/api/v1/user.go b/go_fabric/api/v1/user.go new file mode 100644 index 0000000..d170b96 --- /dev/null +++ b/go_fabric/api/v1/user.go @@ -0,0 +1,80 @@ +package v1 + +import ( + "go_fabric/pkg/util" + "go_fabric/service" + "net/http" + + "github.com/gin-gonic/gin" +) + +func UserRegister(c *gin.Context) { + var userRegister service.UserService + if err := c.ShouldBind(&userRegister); err == nil { + res := userRegister.Register(c.Request.Context()) + c.JSON(http.StatusOK, res) + } else { + c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误 + util.LoggerObj.Error(err) + } +} + +func UserLogin(c *gin.Context) { + var userLogin service.UserService + if err := c.ShouldBind(&userLogin); err == nil { + res := userLogin.Login(c.Request.Context()) + c.JSON(http.StatusOK, res) + } else { + c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误 + util.LoggerObj.Error(err) + } +} + +func UserUpdate(c *gin.Context) { + var userUpdate service.UserService + claims, _ := util.ParseToken(c.GetHeader("Authorization")) + if err := c.ShouldBind(&userUpdate); err == nil { + res := userUpdate.Update(c.Request.Context(), claims.ID) + c.JSON(http.StatusOK, res) + } else { + c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误 + util.LoggerObj.Error(err) + } +} + +func UpdateAvatar(c *gin.Context) { + file, fileHeader, _ := c.Request.FormFile("file") + fileSize := fileHeader.Size + var updateAvatar service.UserService + claims, _ := util.ParseToken(c.GetHeader("Authorization")) + if err := c.ShouldBind(&updateAvatar); err == nil { + res := updateAvatar.Post(c.Request.Context(), claims.ID, file, fileSize) + c.JSON(http.StatusOK, res) + } else { + c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误 + util.LoggerObj.Error(err) + } +} + +func SendEmail(c *gin.Context) { + var sendEmail service.SendEmailService + claims, _ := util.ParseToken(c.GetHeader("Authorization")) + if err := c.ShouldBind(&sendEmail); err == nil { + res := sendEmail.Send(c.Request.Context(), claims.ID) + c.JSON(http.StatusOK, res) + } else { + c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误 + util.LoggerObj.Error(err) + } +} + +func ValidEmail(c *gin.Context) { + var validEmail service.ValidEmailService + if err := c.ShouldBind(&validEmail); err == nil { + res := validEmail.Valid(c.Request.Context(), c.GetHeader("Authorization")) + c.JSON(http.StatusOK, res) + } else { + c.JSON(http.StatusBadRequest, ErrorResponse(err)) //400参数错误 + util.LoggerObj.Error(err) + } +} diff --git a/go_fabric/cache/commen.go b/go_fabric/cache/commen.go new file mode 100644 index 0000000..5bb97f4 --- /dev/null +++ b/go_fabric/cache/commen.go @@ -0,0 +1,47 @@ +package cache + +import ( + "fmt" + "strconv" + + "github.com/go-redis/redis" + "gopkg.in/ini.v1" +) + +var ( + RedisClient *redis.Client + RedisDb string + RedisAddr string + RedisPw string + RedisDbName string +) + +func Init() { + file, err := ini.Load("C:/Users/801028/Desktop/marketv1.2/go_fabric/conf/config.ini") + if err != nil { + fmt.Println("redis config err", err) + } + LoadRedisData(file) + Redis() +} + +func LoadRedisData(file *ini.File) { + RedisDb = file.Section("redis").Key("RedisDb").String() + RedisAddr = file.Section("redis").Key("RedisAddr").String() + RedisPw = file.Section("redis").Key("RedisPw").String() + RedisDbName = file.Section("redis").Key("RedisDbName").String() +} + +func Redis() { + db, _ := strconv.ParseUint(RedisDbName, 10, 64) + client := redis.NewClient(&redis.Options{ + Addr: RedisAddr, + //Password + DB: int(db), + }) + _, err := client.Ping().Result() + if err != nil { + panic(err) + } + RedisClient = client +} diff --git a/go_fabric/cache/key.go b/go_fabric/cache/key.go new file mode 100644 index 0000000..150689b --- /dev/null +++ b/go_fabric/cache/key.go @@ -0,0 +1,14 @@ +package cache + +import ( + "fmt" + "strconv" +) + +const ( + RankKey = "rank" //排名 +) + +func ProductViewKey(id uint) string{ + return fmt.Sprintf("view:product:%s",strconv.Itoa(int(id))) +} \ No newline at end of file diff --git a/go_fabric/cmd/mian.go b/go_fabric/cmd/mian.go new file mode 100644 index 0000000..7b67a91 --- /dev/null +++ b/go_fabric/cmd/mian.go @@ -0,0 +1,14 @@ +package main + +import ( + // "go_fabric/cache" + "go_fabric/conf" + "go_fabric/routes" +) + +func main() { + conf.Init() + // cache.Init() + r := routes.NewRouter() + _ = r.Run(conf.HttpPort) +} diff --git a/go_fabric/conf/config.go b/go_fabric/conf/config.go new file mode 100644 index 0000000..6af96d7 --- /dev/null +++ b/go_fabric/conf/config.go @@ -0,0 +1,86 @@ +package conf + +import ( + "go_fabric/dao" + "strings" + + "gopkg.in/ini.v1" +) + +var ( + AppModel string + HttpPort string + + Db string + DbHost string + DbPort string + DbUser string + DbPassword string + DbName string + + RedisDb string + RedisAddr string + RedisPw string + RedisDbName string + + ValidEmail string + SmtpHost string + SmtpEmail string + SmtpPass string + + Host string + ProductPath string + AvatarPath string +) + +func Init() { + //从本地文件读取环境变量 + file, err := ini.Load("C:/Users/801028/Desktop/marketv1.2/go_fabric/conf/config.ini") + if err != nil { + panic(err) + } + LoadServer(file) + LoadMySql(file) + LoadRedis(file) + LoadEmail(file) + // mysql读 + LoadPhotoPath(file) + PathRead := strings.Join([]string{DbUser, ":", DbPassword, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8mb4&parseTime=true&loc=Local"}, "") + //写 + PathWrite := strings.Join([]string{DbUser, ":", DbPassword, "@tcp(", DbHost, ":", DbPort, ")/", DbName, "?charset=utf8mb4&parseTime=true&loc=Local"}, "") + dao.Database(PathRead, PathWrite) +} + +func LoadServer(file *ini.File) { + AppModel = file.Section("service").Key("AppMode").String() + HttpPort = file.Section("service").Key("HttpPort").String() +} + +func LoadMySql(file *ini.File) { + Db = file.Section("mysql").Key("DB").String() + DbHost = file.Section("mysql").Key("DbHost").String() + DbPort = file.Section("mysql").Key("DbPort").String() + DbUser = file.Section("mysql").Key("DbUser").String() + DbPassword = file.Section("mysql").Key("DbPassword").String() + DbName = file.Section("mysql").Key("DbName").String() +} + +func LoadRedis(file *ini.File) { + RedisDb = file.Section("redis").Key("RedisDb").String() + RedisAddr = file.Section("redis").Key("RedisAddr").String() + RedisPw = file.Section("redis").Key("RedisPw").String() + RedisDbName = file.Section("redis").Key("RedisDbName").String() +} + +func LoadEmail(file *ini.File) { + ValidEmail = file.Section("email").Key("ValidEmail").String() + SmtpHost = file.Section("email").Key("SmtpHost").String() + SmtpEmail = file.Section("email").Key("SmtpEmail").String() + SmtpPass = file.Section("email").Key("SmtpPass").String() +} + +func LoadPhotoPath(file *ini.File) { + Host = file.Section("path").Key("Host").String() + ProductPath = file.Section("path").Key("ProductPath").String() + AvatarPath = file.Section("path").Key("AvatarPath").String() +} diff --git a/go_fabric/conf/config.ini b/go_fabric/conf/config.ini new file mode 100644 index 0000000..ce7dfb6 --- /dev/null +++ b/go_fabric/conf/config.ini @@ -0,0 +1,36 @@ +[service] +AppMode = debug +HttpPort = :3000 + +[mysql] +DB = mysql +DbHost = 127.0.0.1 +DbPort = 3306 +DbUser = root +DbPassword = 240011@rbb +DbName = poem + +[redis] +RedisDb = redis +RedisAddr = 127.0.0.1:6379 +RedisPw = +RedisDbName = 2 + +[qiniu] +AccessKey = +SecretKey = +Bucket = +QiniuServer = + +[email] +ValidEmail = http://localhost:8080/#/vaild/email/ +SmtpHost = smtp.qq.com +SmtpEmail = 1065109019@qq.com +; 管理员邮箱 +SmtpPass = coziejecpksvbbcf +; 授权码 + +[path] +Host = http://127.0.0.1 +ProductPath =C:/Users/801028/Desktop/marketv1.2/go_fabric/static/imags/Product/ +AvatarPath =C:/Users/801028/Desktop/marketv1.2/static/imags/avatar/ diff --git a/go_fabric/dao/init.go b/go_fabric/dao/init.go new file mode 100644 index 0000000..21fb482 --- /dev/null +++ b/go_fabric/dao/init.go @@ -0,0 +1,61 @@ +package dao + +import ( + "context" + "time" + + "github.com/gin-gonic/gin" + "gorm.io/driver/mysql" + "gorm.io/gorm" + "gorm.io/gorm/logger" + "gorm.io/gorm/schema" + "gorm.io/plugin/dbresolver" +) + +var _db *gorm.DB + +func Database(connRead, connWrite string) { + var ormLogger logger.Interface + if gin.Mode() == "debug" { + ormLogger = logger.Default.LogMode(logger.Info) + } else { + ormLogger = logger.Default + } + + db, err := gorm.Open(mysql.New(mysql.Config{ + DSN: connRead, + DefaultStringSize: 256, //string类型字段默认长度 + DisableDatetimePrecision: true, //禁止datatime精度 + DontSupportRenameIndex: true, //重命名索引,需要先删除索引再重建 + DontSupportRenameColumn: true, //用change重命名列,mysql 8之前不支持 + SkipInitializeWithVersion: false, + }), &gorm.Config{ + Logger: ormLogger, + NamingStrategy: schema.NamingStrategy{ + SingularTable: true, + }, + }) + if err != nil { + return + } + sqlDB, _ := db.DB() + sqlDB.SetMaxOpenConns(20) //设置连接池 + sqlDB.SetMaxOpenConns(100) //打开连接数 + sqlDB.SetConnMaxLifetime(time.Second * 30) + _db = db + + // 主从配置 + _ = _db.Use(dbresolver. + Register(dbresolver.Config{ + Sources: []gorm.Dialector{mysql.Open(connWrite)}, //写操作 + Replicas: []gorm.Dialector{mysql.Open(connRead), mysql.Open(connRead)}, //读操作 + Policy: dbresolver.RandomPolicy{}, + })) + //数据库迁移 + migration() +} + +func NewDBClient(ctx context.Context) *gorm.DB { + db := _db + return db.WithContext(ctx) +} diff --git a/go_fabric/dao/migration.go b/go_fabric/dao/migration.go new file mode 100644 index 0000000..a3fbbde --- /dev/null +++ b/go_fabric/dao/migration.go @@ -0,0 +1,17 @@ +package dao + +import ( + "fmt" + "go_fabric/model" +) + +func migration() { + err := _db.Set("gorm:table_options", "charset=utf8mb4"). + AutoMigrate( + &model.Poem{}, + ) + if err != nil { + fmt.Println("err", err) + } + return +} diff --git a/go_fabric/dao/poem.go b/go_fabric/dao/poem.go new file mode 100644 index 0000000..e5e1eaa --- /dev/null +++ b/go_fabric/dao/poem.go @@ -0,0 +1,64 @@ +package dao + +import ( + "context" + "go_fabric/model" + + "gorm.io/gorm" +) + +type UserDao struct { + *gorm.DB +} + +func NewUserDao(ctx context.Context) *UserDao { + return &UserDao{NewDBClient(ctx)} +} + +func NewUserDaoDB(db *gorm.DB) *UserDao { + return &UserDao{db} +} + +// 是否存在该用户名用户 +func (dao *UserDao) ExistOrNotByUserName(userName string) (user *model.User, exist bool, err error) { + var count int64 + err = dao.DB.Model(&model.User{}).Where("user_name=?", userName).Find(&user).Count(&count).Error + if count == 0 { + return nil, false, err + } + return user, true, nil +} + +// 添加用户 +func (dao *UserDao) CreateUser(user *model.User) error { + return dao.DB.Model(&model.User{}).Create(&user).Error +} + +// 根据Id寻找用户 +func (dao *UserDao) GetUserById(id uint) (user *model.User, err error) { + err = dao.DB.Model(&model.User{}).Where("id=?", id).First(&user).Error + return +} + +// 查询所有用户 列表 +// offset表示偏移量,pageSize表示每页数据量,pageNum表示当前查询的页码数 +func (dao *UserDao) ListUser(pageNum int, pageSize int) (users []model.User, err error) { + offset := (pageNum - 1) * pageSize + err = dao.DB.Model(&model.User{}).Offset(offset).Limit(pageSize).Find(&users).Error + return +} + +// 根据id修改用户信息 +func (dao *UserDao) UpdateUserById(uId uint, user *model.User) error { + return dao.DB.Model(&model.User{}).Where("id=?", uId).Updates(&user).Error +} + +// 根据用户名删除用户 +func (dao *UserDao) DeleteByUserName(user *model.User) error { + return dao.DB.Delete(&user).Error +} + +// 封禁用户 +func (dao *UserDao) PassiveByUserName(uId uint) error { + return dao.DB.Model(&model.User{}).Where("id=?", uId).Update("status", "passive").Error +} diff --git a/go_fabric/go.mod b/go_fabric/go.mod new file mode 100644 index 0000000..3fc6b34 --- /dev/null +++ b/go_fabric/go.mod @@ -0,0 +1,44 @@ +module go_fabric + +go 1.20 + +require github.com/gin-gonic/gin v1.9.1 + +require ( + github.com/bytedance/sonic v1.9.2 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.14.1 // indirect + github.com/go-redis/redis v6.15.9+incompatible // indirect + github.com/go-sql-driver/mysql v1.7.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // indirect + github.com/leodido/go-urn v1.2.4 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect + golang.org/x/arch v0.4.0 // indirect + golang.org/x/crypto v0.11.0 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/mail.v2 v2.3.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/mysql v1.5.1 // indirect + gorm.io/gorm v1.25.2 // indirect + gorm.io/plugin/dbresolver v1.4.1 // indirect +) diff --git a/go_fabric/go.sum b/go_fabric/go.sum new file mode 100644 index 0000000..398395c --- /dev/null +++ b/go_fabric/go.sum @@ -0,0 +1,109 @@ +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.9.2 h1:GDaNjuWSGu09guE9Oql0MSTNhNCLlWwO8y/xM5BzcbM= +github.com/bytedance/sonic v1.9.2/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= +github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= +github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= +github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= +golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= +gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.4.3/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10c= +gorm.io/driver/mysql v1.5.1 h1:WUEH5VF9obL/lTtzjmML/5e6VfFR/788coz2uaVCAZw= +gorm.io/driver/mysql v1.5.1/go.mod h1:Jo3Xu7mMhCyj8dlrb3WoCaRd1FhsVh+yMXb1jUInf5o= +gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= +gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= +gorm.io/gorm v1.25.1/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho= +gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/plugin/dbresolver v1.4.1 h1:Ug4LcoPhrvqq71UhxtF346f+skTYoCa/nEsdjvHwEzk= +gorm.io/plugin/dbresolver v1.4.1/go.mod h1:CTbCtMWhsjXSiJqiW2R8POvJ2cq18RVOl4WGyT5nhNc= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/go_fabric/middleware/cors.go b/go_fabric/middleware/cors.go new file mode 100644 index 0000000..46f33a9 --- /dev/null +++ b/go_fabric/middleware/cors.go @@ -0,0 +1,45 @@ +package middleware + +import ( + "fmt" + "net/http" + "strings" + + "github.com/gin-gonic/gin" +) + +// 跨域 +func Cors() gin.HandlerFunc { + return func(c *gin.Context) { + method := c.Request.Method //请求方法 + origin := c.Request.Header.Get("Origin") //请求头部 + var headerKeys []string // 声明请求头keys + for k := range c.Request.Header { + headerKeys = append(headerKeys, k) + } + headerStr := strings.Join(headerKeys, ", ") + if headerStr != "" { + headerStr = fmt.Sprintf("access-control-allow-origin, access-control-allow-headers, %s", headerStr) + } else { + headerStr = "access-control-allow-origin, access-control-allow-headers" + } + if origin != "" { + c.Writer.Header().Set("Access-Control-Allow-Origin", "*") + c.Header("Access-Control-Allow-Origin", "*") // 这是允许访问所有域 + c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") //服务器支持的所有跨域请求的方法,为了避免浏览次请求的多次'预检'请求 + // header的类型 + c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma") + // 允许跨域设置 可以返回其他子段 + c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar") // 跨域关键设置 让浏览器可以解析 + c.Header("Access-Control-Max-Age", "172800") // 缓存请求信息 单位为秒 + c.Header("Access-Control-Allow-Credentials", "false") // 跨域请求是否需要带cookie信息 默认设置为true + c.Set("content-type", "application/json") // 设置返回格式是json + } + //放行所有OPTIONS方法 + if method == "OPTIONS" { + c.JSON(http.StatusOK, "Options Request!") + } + // 处理请求 + c.Next() // 处理请求 + } +} diff --git a/go_fabric/middleware/jwt.go b/go_fabric/middleware/jwt.go new file mode 100644 index 0000000..640bb07 --- /dev/null +++ b/go_fabric/middleware/jwt.go @@ -0,0 +1,36 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "go_fabric/pkg/e" + "go_fabric/pkg/util" + "time" +) + +func JWT() gin.HandlerFunc { + return func(c *gin.Context) { + var code int + //var data interface{} + code = 200 + token := c.GetHeader("Authorization") + if token == "" { + code = 404 + } else { + claims, err := util.ParseToken(token) + if err != nil { + code = e.ErrorToken + } else if time.Now().Unix() > claims.ExpiresAt { + code = e.ErrorCheckTokenTimeOut + } + } + if code != e.Success { + c.JSON(200, gin.H{ + "status": code, + "msg": e.GetMsg(code), + }) + c.Abort() + return + } + c.Next() + } +} diff --git a/go_fabric/model/poem.go b/go_fabric/model/poem.go new file mode 100644 index 0000000..66af1a4 --- /dev/null +++ b/go_fabric/model/poem.go @@ -0,0 +1,9 @@ +package model + +import "gorm.io/gorm" + +type Poem struct { + gorm.Model + Id uint `gorm:"not null"` + Content string +} diff --git a/go_fabric/pkg/e/code.go b/go_fabric/pkg/e/code.go new file mode 100644 index 0000000..f757908 --- /dev/null +++ b/go_fabric/pkg/e/code.go @@ -0,0 +1,29 @@ +package e + +const ( + Success = 200 + Error = 500 + InvalidParams = 400 + + //user模块错误 + ErrorExistUser = 30001 + ErrorFailEncryption = 30002 + NullPassword = 30003 + UserNotFind = 30004 + ErrorPassword = 30005 + ErrorToken = 30006 + ErrorCheckTokenTimeOut = 30007 + ErrorUploadFail = 30008 + ErrorSendEmail = 30009 + ErrorNotActive = 30010 + + //product模块错误 + ErrorProductImgUpload = 40001 + ProductNotFind = 40002 + ErrorBossForProduct = 40003 + ErrorNotSale = 40004 + ErrorProductNum = 40005 + + //收藏夹模块 + ErrorFavoriteExist = 50001 +) diff --git a/go_fabric/pkg/e/msg.go b/go_fabric/pkg/e/msg.go new file mode 100644 index 0000000..e43917d --- /dev/null +++ b/go_fabric/pkg/e/msg.go @@ -0,0 +1,39 @@ +package e + +var MsgFlags = map[int]string{ + Success: "ok", + Error: "fail", + InvalidParams: "参数错误", + + //user模块错误 + ErrorExistUser: "用户已存在", + NullPassword: "密码不能为空", + ErrorFailEncryption: "密码加密失败", + UserNotFind: "用户不存在", + ErrorPassword: "密码错误", + ErrorToken: "token验证失败", + ErrorCheckTokenTimeOut: "token过期", + ErrorUploadFail: "图片上传失败", + ErrorSendEmail: "邮件发送失败", + ErrorNotActive: "用户未激活", + + //product模块错误 + ErrorProductImgUpload: "商品图片上传失败", + ProductNotFind: "商品不存在", + ErrorBossForProduct: "商品与商户不匹配", + ErrorNotSale: "商品不在售", + ErrorProductNum: "商品数量错误", + + //收藏夹模块 + ErrorFavoriteExist: "收藏夹已存在", +} + +// GetMsg 获取状态码对应信息 +func GetMsg(code int) string { + msg, ok := MsgFlags[code] + if !ok { + return MsgFlags[Error] + } else { + return msg + } +} diff --git a/go_fabric/pkg/util/enceypt.go b/go_fabric/pkg/util/enceypt.go new file mode 100644 index 0000000..7f8ac75 --- /dev/null +++ b/go_fabric/pkg/util/enceypt.go @@ -0,0 +1,88 @@ +package util + +import ( + "bytes" + "crypto/aes" + "encoding/base64" + "errors" +) + +var Encrypt *Encryption + +// AES 加密算法 +type Encryption struct { + key string +} + +func init() { + Encrypt = NewEncryption() +} + +func NewEncryption() *Encryption { + return &Encryption{} +} + +// 填充密码长度 +func PadPwd(srcByte []byte, blockSize int) []byte { + padNum := blockSize - len(srcByte)%blockSize + ret := bytes.Repeat([]byte{byte(padNum)}, padNum) + srcByte = append(srcByte, ret...) + return srcByte +} + +// 加密 +func (k *Encryption) AesEncoding(src string) string { + srcByte := []byte(src) + block, err := aes.NewCipher([]byte(k.key)) + if err != nil { + return src + } + // 密码填充 + NewSrcByte := PadPwd(srcByte, block.BlockSize()) //由于字节长度不够,所以要进行字节的填充 + dst := make([]byte, len(NewSrcByte)) + block.Encrypt(dst, NewSrcByte) + // base64 编码 + pwd := base64.StdEncoding.EncodeToString(dst) + return pwd +} + +// 去掉填充的部分 +func UnPadPwd(dst []byte) ([]byte, error) { + if len(dst) <= 0 { + return dst, errors.New("长度有误") + } + // 去掉的长度 + unpadNum := int(dst[len(dst)-1]) + strErr := "error" + op := []byte(strErr) + if len(dst) < unpadNum { + return op, nil + } + str := dst[:(len(dst) - unpadNum)] + return str, nil +} + +// 解密 +func (k *Encryption) AesDecoding(pwd string) string { + pwdByte := []byte(pwd) + pwdByte, err := base64.StdEncoding.DecodeString(pwd) + if err != nil { + return pwd + } + block, errBlock := aes.NewCipher([]byte(k.key)) + if errBlock != nil { + return pwd + } + dst := make([]byte, len(pwdByte)) + block.Decrypt(dst, pwdByte) + dst, err = UnPadPwd(dst) // 填充的要去掉 + if err != nil { + return "0" + } + return string(dst) +} + +// set方法 +func (k *Encryption) SetKey(key string) { + k.key = key +} diff --git a/go_fabric/pkg/util/jwt.go b/go_fabric/pkg/util/jwt.go new file mode 100644 index 0000000..b5ca521 --- /dev/null +++ b/go_fabric/pkg/util/jwt.go @@ -0,0 +1,87 @@ +package util + +import ( + "github.com/dgrijalva/jwt-go" + "time" +) + +var jwtSecret = []byte("test") + +// 用户唯一token信息类 +type Claims struct { + ID uint `json:"id"` + UserName string `json:"user_name"` + Authority int `json:"authority"` //权限 + jwt.StandardClaims +} + +// token分发 +func GenerateToken(id uint, userName string, authority int) (string, error) { + nowTime := time.Now() + endTime := nowTime.Add(24 * time.Hour) + claims := Claims{ + ID: id, + UserName: userName, + Authority: authority, + StandardClaims: jwt.StandardClaims{ + ExpiresAt: endTime.Unix(), + Issuer: "test-mall", + }, + } + tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) //哈希256加密 + token, err := tokenClaims.SignedString(jwtSecret) //数字签名 + return token, err +} + +// token验证 +func ParseToken(token string) (*Claims, error) { + tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) { + return jwtSecret, nil + }) + if tokenClaims != nil { + if claims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid { + return claims, nil + } + } + return nil, err +} + +type EmailClaims struct { + UserID uint `json:"user_id"` + Email string `json:"email"` + Password string `json:"password"` + OperationType uint `json:"operation_type"` + jwt.StandardClaims +} + +// 签发email token +func GenerateEmailToken(userId, Operation uint, email, password string) (string, error) { + nowTime := time.Now() + endTime := nowTime.Add(24 * time.Hour) + claims := EmailClaims{ + UserID: userId, + Email: email, + Password: password, + OperationType: Operation, + StandardClaims: jwt.StandardClaims{ + ExpiresAt: endTime.Unix(), + Issuer: "test-mall", + }, + } + tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) //哈希256加密 + token, err := tokenClaims.SignedString(jwtSecret) //数字签名 + return token, err +} + +// 解密email token +func ParseEmailToken(token string) (*EmailClaims, error) { + tokenClaims, err := jwt.ParseWithClaims(token, &EmailClaims{}, func(token *jwt.Token) (interface{}, error) { + return jwtSecret, nil + }) + if tokenClaims != nil { + if claims, ok := tokenClaims.Claims.(*EmailClaims); ok && tokenClaims.Valid { + return claims, nil + } + } + return nil, err +} diff --git a/go_fabric/pkg/util/logger.go b/go_fabric/pkg/util/logger.go new file mode 100644 index 0000000..5572a33 --- /dev/null +++ b/go_fabric/pkg/util/logger.go @@ -0,0 +1,59 @@ +package util + +import ( + "github.com/sirupsen/logrus" + "log" + "os" + "path" + "time" +) + +// 日志打印 +var LoggerObj *logrus.Logger + +func init() { + src, _ := setOutPutFile() + if LoggerObj != nil { + LoggerObj.Out = src + return + } + //实例化 + logger := logrus.New() + logger.Out = src //设置输出 + logger.SetLevel(logrus.DebugLevel) //设置日志级别 + logger.SetFormatter(&logrus.TextFormatter{ + TimestampFormat: "2006-01-02 15:04:05", + }) + LoggerObj = logger +} + +func setOutPutFile() (*os.File, error) { + now := time.Now() + logFilePath := "" + if dir, err := os.Getwd(); err == nil { //工作目录下 + logFilePath = dir + "/logs/" + } + _, err := os.Stat(logFilePath) + if os.IsNotExist(err) { + if err = os.MkdirAll(logFilePath, 0777); err != nil { + log.Println(err.Error()) + return nil, err + } + } + logFileName := now.Format("2006-1-02") + ".log" + //日志文件 + fileName := path.Join(logFilePath, logFileName) + _, err = os.Stat(fileName) + if os.IsNotExist(err) { + if err = os.MkdirAll(fileName, 0777); err != nil { + log.Println(err.Error()) + return nil, err + } + } + // 写入文件 + src, err := os.OpenFile(fileName, os.O_APPEND|os.O_WRONLY, os.ModeAppend) + if err != nil { + return nil, err + } + return src, nil +} diff --git a/go_fabric/routes/router.go b/go_fabric/routes/router.go new file mode 100644 index 0000000..e78c592 --- /dev/null +++ b/go_fabric/routes/router.go @@ -0,0 +1,40 @@ +package routes + +import ( + api "go_fabric/api/v1" + "go_fabric/middleware" + "net/http" + + "github.com/gin-gonic/gin" +) + +func NewRouter() *gin.Engine { + r := gin.Default() + + r.Use(middleware.Cors()) + r.StaticFS("/static", http.Dir("C:/Users/801028/Desktop/marketv1.2/go_fabric/static/")) + // jr.StaticFile("/avatar.jpg", "/GOCODE/go_fabric/static/imags/avatar/avatar.jpg") + v1 := r.Group("api/v1") + { + v1.GET("ping", func(ctx *gin.Context) { + ctx.JSON(200, "success") + }) + //获取诗词 + v1.GET("poem/gain", api.PoemGet) + + //用户操作 + v1.POST("user/register", api.UserRegister) + v1.POST("user/login", api.UserLogin) + + authed := v1.Group("/") //登录保护 + authed.Use(middleware.JWT()) + { + // 用户操作 + authed.PUT("user", api.UserUpdate) //用户信息更新 + authed.POST("avatar", api.UpdateAvatar) //用户上传头像 + authed.POST("user/send-email", api.SendEmail) //发送验证邮件 + authed.POST("user/valid-email", api.ValidEmail) //绑定邮箱 + } + } + return r +} diff --git a/go_fabric/serializer/common.go b/go_fabric/serializer/common.go new file mode 100644 index 0000000..9bbb90d --- /dev/null +++ b/go_fabric/serializer/common.go @@ -0,0 +1,39 @@ +package serializer + +type Response struct { + Status int `json:"status"` + Data interface{} `json:"data"` + Msg string `json:"msg"` + Error string `json:"error"` +} + +type TokenData struct { + User interface{} `json:"user"` + Token string `json:"tokens"` +} + +type AdminToken struct { + Admin interface{} `json:"admin"` + Token string `json:"tokens"` +} + +type BossToken struct { + Boss interface{} `json:"boss"` + Token string `json:"tokens"` +} + +type DataList struct { + Item interface{} `json:"item"` + Total uint `json:"total"` +} + +func BuildListResponse(items interface{}, total uint) Response { + return Response{ + Status: 200, + Data: DataList{ + Item: items, + Total: total, + }, + Msg: "ok", + } +} diff --git a/go_fabric/serializer/poem.go b/go_fabric/serializer/poem.go new file mode 100644 index 0000000..3be7958 --- /dev/null +++ b/go_fabric/serializer/poem.go @@ -0,0 +1,26 @@ +package serializer + +import ( + "go_fabric/model" +) + +// Vo 向前端展示 +type PoemVo struct { + Id uint `json:"id"` + Content string `json:"content"` +} + +func BuildUser(poem *model.Poem) PoemVo { + return PoemVo{ + Id: poem.Id, + Content: poem.Content, + } +} + +func BuildUsers(items []model.Poem) (users []PoemVo) { + for _, item := range items { + poem := BuildUser(&item) + poems = append(poems, poem) + } + return poems +} diff --git a/go_fabric/service/poem.go b/go_fabric/service/poem.go new file mode 100644 index 0000000..cc72525 --- /dev/null +++ b/go_fabric/service/poem.go @@ -0,0 +1,379 @@ +package service + +import ( + "context" + "fmt" + "go_fabric/conf" + "go_fabric/dao" + "go_fabric/model" + "go_fabric/pkg/e" + "go_fabric/pkg/util" + "go_fabric/serializer" + "mime/multipart" + "strings" + "time" + + "gopkg.in/mail.v2" +) + +type UserService struct { + NickName string `json:"nick_name" form:"nick_name"` + UserName string `json:"user_name" form:"user_name"` + Password string `json:"password" form:"password"` + Key string `json:"key" form:"key"` //加密密钥 +} + +type SendEmailService struct { + Email string `json:"email" form:"email"` + Password string `json:"password"` + OperationType uint `json:"operation_type" form:"operation_type"` // 1.绑定邮箱 2.解绑邮箱 3.更改密码 +} + +type ValidEmailService struct { +} + +// 注册 +func (service *UserService) Register(ctx context.Context) serializer.Response { + var user model.User + code := e.Success + if service.Key == "" || len(service.Key) != 6 { + code = e.Error + return serializer.Response{ + Status: code, + Data: nil, + Msg: e.GetMsg(code), + Error: "密钥长度不符", + } + } + util.Encrypt.SetKey(service.Key) + + userDao := dao.NewUserDao(ctx) + _, exist, err := userDao.ExistOrNotByUserName(service.UserName) + if err != nil { + util.LoggerObj.Error(err) + code = e.Error + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } + } + if exist { + code = e.ErrorExistUser + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } + } + user = model.User{ + UserName: service.UserName, + NickName: service.NickName, + Avatar: "avatar.JPG", + Status: model.Active, + Money: "1000", + Vip: 0, + } + //密码是否为空 + if service.Password == "" { + code = e.NullPassword + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } + } + //密码加密 + if err = user.SetPassword(service.Password); err != nil { + util.LoggerObj.Error(err) + code = e.ErrorFailEncryption + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } + } + //创建用户 + err = userDao.CreateUser(&user) + if err != nil { + util.LoggerObj.Error(err) + code = e.Error + } + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } +} + +// 登录 +func (service *UserService) Login(ctx context.Context) serializer.Response { + var user *model.User + code := e.Success + userDao := dao.NewUserDao(ctx) + //检查用户是否存在 + user, exist, err := userDao.ExistOrNotByUserName(service.UserName) + if !exist || err != nil { + util.LoggerObj.Error(err) + code = e.UserNotFind + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Data: "用户不存在,请先注册", + } + } + //验证密码是否正确 + if user.CheckPassword(service.Password) == false { + code = e.ErrorPassword + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Data: "密码错误,请重新输入", + } + } + //分发token + token, err := util.GenerateToken(user.ID, service.UserName, 0) + if err != nil { + util.LoggerObj.Error(err) + code = e.ErrorToken + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Data: "token验证失败", + } + } + return serializer.Response{ + Status: code, + Data: serializer.TokenData{User: serializer.BuildUser(user), Token: token}, + Msg: e.GetMsg(code), + } +} + +// 用户修改信息 +func (service *UserService) Update(ctx context.Context, uId uint) serializer.Response { + var user *model.User + var err error + code := e.Success + //寻找用户 + userDao := dao.NewUserDao(ctx) + user, err = userDao.GetUserById(uId) + + //检查用户状态 + if user.Status == "passive" { + code = e.ErrorNotActive + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Error: "用户没有激活,没有权限", + } + } + + //修改昵称nickname + if service.NickName != "" { + user.NickName = service.NickName + } + err = userDao.UpdateUserById(uId, user) + if err != nil { + util.LoggerObj.Error(err) + code = e.Error + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } + } + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Data: serializer.BuildUser(user), + } +} + +// 头像更新 +func (service *UserService) Post(ctx context.Context, uId uint, file multipart.File, fileSize int64) serializer.Response { + code := e.Success + var user *model.User + var err error + userDao := dao.NewUserDao(ctx) + user, err = userDao.GetUserById(uId) + + if user.Status == "passive" { + code = e.ErrorNotActive + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Error: "用户没有激活,没有权限", + } + } + + if err != nil { + code = e.Error + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Error: err.Error(), + } + } + //保存图片到本地 + path, err := UploadAvatarLocalStatic(file, uId, user.UserName) + if err != nil { + code = e.ErrorUploadFail + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Error: err.Error(), + } + } + user.Avatar = path + err = userDao.UpdateUserById(uId, user) + if err != nil { + util.LoggerObj.Error(err) + code = e.Error + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Error: err.Error(), + } + } + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Data: serializer.BuildUser(user), + } +} + +// 发送验证邮件 +func (service *SendEmailService) Send(ctx context.Context, uId uint) serializer.Response { + code := e.Success + var address string + var notice *model.Notice // 绑定邮箱,修改密码 模板通知 + + userDao := dao.NewUserDao(ctx) + user, err := userDao.GetUserById(uId) + //检查用户状态 + if user.Status == "passive" { + code = e.ErrorNotActive + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Error: "用户没有激活,没有权限", + } + } + + token, err := util.GenerateEmailToken(uId, service.OperationType, service.Email, service.Password) + if err != nil { + util.LoggerObj.Error(err) + code = e.ErrorToken + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Error: err.Error(), + } + } + noticeDao := dao.NewNoticeDao(ctx) + notice, err = noticeDao.GetNoticeById(service.OperationType) + if err != nil { + util.LoggerObj.Error(err) + code = e.Error + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Error: err.Error(), + } + } + address = conf.ValidEmail + token //发送者 + mailStr := notice.Text + mailText := strings.Replace(mailStr, "+", address, -1) + fmt.Println(mailText) + m := mail.NewMessage() + m.SetHeader("From", conf.SmtpEmail) //管理员邮箱 + m.SetHeader("To", service.Email) //验证者邮箱 + m.SetHeader("Subject", "fabric_mall") + m.SetBody("text/html", mailText) + d := mail.NewDialer(conf.SmtpHost, 465, conf.SmtpEmail, conf.SmtpPass) + d.StartTLSPolicy = mail.MandatoryStartTLS + if err = d.DialAndSend(m); err != nil { + util.LoggerObj.Error(err) + code = e.ErrorSendEmail + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Error: err.Error(), + } + } + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } +} + +// 验证邮箱 +func (service *ValidEmailService) Valid(ctx context.Context, token string) serializer.Response { + var userId uint + var email string + var password string + var operationType uint + code := e.Success + //验证token + if token == "" { + code = e.InvalidParams + + } else { + claims, err := util.ParseEmailToken(token) + if err != nil { + util.LoggerObj.Error(err) + code = e.ErrorToken + + } else if time.Now().Unix() > claims.ExpiresAt { + code = e.ErrorCheckTokenTimeOut + + } else { + userId = claims.UserID + email = claims.Email + password = claims.Password + operationType = claims.OperationType + } + } + if code != e.Success { + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } + } + + // token解析成功,获取用户信息 + userDao := dao.NewUserDao(ctx) + user, err := userDao.GetUserById(userId) + if err != nil { + util.LoggerObj.Error(err) + code = e.Error + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } + } + + if operationType == 1 { //1.绑定邮箱 + user.Email = email + } else if operationType == 2 { //2.解绑邮箱 + user.Email = "" + } else if operationType == 3 { //3.修改密码 + err = user.SetPassword(password) + if err != nil { + util.LoggerObj.Error(err) + code = e.Error + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } + } + } + err = userDao.UpdateUserById(userId, user) + if err != nil { + util.LoggerObj.Error(err) + code = e.Error + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + } + } + return serializer.Response{ + Status: code, + Msg: e.GetMsg(code), + Data: serializer.BuildUser(user), + } +} diff --git a/go_fabric/test.go b/go_fabric/test.go new file mode 100644 index 0000000..1f2794a --- /dev/null +++ b/go_fabric/test.go @@ -0,0 +1,17 @@ +package main + +import ( + "github.com/gin-gonic/gin" +) + +func main() { + router := gin.Default() + + router.GET("/index", func(ctx *gin.Context) { + ctx.String(200, "hellpo_world") + }) + + router.StaticFile("/avatar.jpg", "/gocode/go_fabric/static/imags/avatar/avatar.jpg") + + router.Run(":8080") +}