公司pc的代码merge
parent
974c3d6fc8
commit
bc2de61c4d
|
@ -1,2 +1,3 @@
|
||||||
glide.yaml
|
glide.yaml
|
||||||
api_user.exe
|
api_user.exe
|
||||||
|
user.exe
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
)
|
)
|
||||||
|
@ -12,14 +12,14 @@ var ostype = runtime.GOOS
|
||||||
var conf ConfAPI
|
var conf ConfAPI
|
||||||
|
|
||||||
type ConfAPI struct {
|
type ConfAPI struct {
|
||||||
ListenSvr int `yaml:"listen_svr"` // 服务监听端口
|
ListenSvr int `yaml:"listen_svr"` // 服务监听端口
|
||||||
ListenApi int `yaml:"listen_api"` // 服务监听端口
|
ListenApi int `yaml:"listen_api"` // 服务监听端口
|
||||||
RunMode string `yaml:"runmode"` // 服务运行模式
|
RunMode string `yaml:"runmode"` // 服务运行模式
|
||||||
MaxConn int `yaml:"max_conn"`
|
MaxConn int `yaml:"max_conn"`
|
||||||
Logs LogConfig `yaml:"logs"` // 日志
|
Logs LogConfig `yaml:"logs"` // 日志
|
||||||
Redis1 EntityRedis `yaml:"redis1"`
|
Redis1 EntityRedis `yaml:"redis1"`
|
||||||
Mysql MysqlConfig `yaml:"mysql"` // 认证配置
|
Mysql MysqlConfig `yaml:"mysql"` // 认证配置
|
||||||
init bool
|
init bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type EntityRedis struct {
|
type EntityRedis struct {
|
||||||
|
@ -47,18 +47,20 @@ type MysqlConfig struct {
|
||||||
MaxOpen int `yaml:"max_open"`
|
MaxOpen int `yaml:"max_open"`
|
||||||
MaxIdle int `yaml:"max_idle"`
|
MaxIdle int `yaml:"max_idle"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var gConf ConfAPI
|
var gConf ConfAPI
|
||||||
|
|
||||||
func Init(path string) error {
|
func Init(path string) error {
|
||||||
file,e := os.Open(path)
|
file, e := os.Open(path)
|
||||||
if nil != e{
|
if nil != e {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
stat,_ := file.Stat()
|
stat, _ := file.Stat()
|
||||||
filec := make([]byte, stat.Size())
|
filec := make([]byte, stat.Size())
|
||||||
file.Read(filec)
|
file.Read(filec)
|
||||||
e = yaml.Unmarshal(filec,&gConf)
|
e = yaml.Unmarshal(filec, &gConf)
|
||||||
if nil != e{
|
if nil != e {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
}
|
}
|
||||||
gConf.init = true
|
gConf.init = true
|
||||||
|
@ -66,30 +68,30 @@ func Init(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPort() int {
|
func GetPort() int {
|
||||||
if gConf.init{
|
if gConf.init {
|
||||||
return gConf.ListenApi
|
return gConf.ListenApi
|
||||||
}else {
|
} else {
|
||||||
return 8001
|
return 8001
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func GetMysqlConfig() *MysqlConfig{
|
func GetMysqlConfig() *MysqlConfig {
|
||||||
if gConf.init{
|
if gConf.init {
|
||||||
return &gConf.Mysql
|
return &gConf.Mysql
|
||||||
}else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func GetRedis1() *EntityRedis {
|
func GetRedis1() *EntityRedis {
|
||||||
if gConf.init{
|
if gConf.init {
|
||||||
return &gConf.Redis1
|
return &gConf.Redis1
|
||||||
}else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func GetLogConfig() *LogConfig {
|
func GetLogConfig() *LogConfig {
|
||||||
if gConf.init{
|
if gConf.init {
|
||||||
return &gConf.Logs
|
return &gConf.Logs
|
||||||
}else{
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,12 @@ func initRedis(addr string, pwd string, db int, coon int) (*redis.Client, error)
|
||||||
|
|
||||||
func InitRedis() error {
|
func InitRedis() error {
|
||||||
redisConf := GetRedis1()
|
redisConf := GetRedis1()
|
||||||
if nil == redisConf{
|
if nil == redisConf {
|
||||||
return errors.New("Error Config Redis")
|
return errors.New("Error Config Redis")
|
||||||
}else {
|
} else {
|
||||||
var e error
|
var e error
|
||||||
gRedis1,e = initRedis(GetRedis1().Addr,GetRedis1().Pwd,GetRedis1().DB,GetRedis1().PoolSize)
|
gRedis1, e = initRedis(GetRedis1().Addr, GetRedis1().Pwd, GetRedis1().DB, GetRedis1().PoolSize)
|
||||||
if nil != e{
|
if nil != e {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
package _const
|
package _const
|
||||||
|
|
||||||
var RespCode map[int]string
|
var RespCode map[int]string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RESP_ERR_COMON = 101
|
RESP_ERR_COMON = 101
|
||||||
RESP_ERR_OK = 0
|
RESP_ERR_OK = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
RespCode[RESP_ERR_OK] = "OK"
|
RespCode[RESP_ERR_OK] = "OK"
|
||||||
RespCode[RESP_ERR_COMON] = "Err"
|
RespCode[RESP_ERR_COMON] = "Err"
|
||||||
}
|
}
|
||||||
func M(key int) string{
|
func M(key int) string {
|
||||||
v,ok := RespCode[key]
|
v, ok := RespCode[key]
|
||||||
if ok{
|
if ok {
|
||||||
return v
|
return v
|
||||||
}else {
|
} else {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,28 +27,28 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ReqSendEmailCode struct {
|
type ReqSendEmailCode struct {
|
||||||
EmailAdress string `json:"email_address"`
|
EmailAdress string `json:"email_address"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SetUserGroupReq struct {
|
type SetUserGroupReq struct {
|
||||||
Id int64 `json:"id,omitempty"`
|
Id int64 `json:"id,omitempty"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
GroupName string `json:"group_name"`
|
GroupName string `json:"group_name"`
|
||||||
UserIds []int `json:"user_ids"`
|
UserIds []int `json:"user_ids"`
|
||||||
}
|
}
|
||||||
type RespBase struct {
|
type RespBase struct {
|
||||||
Msg string
|
Msg string
|
||||||
Status int
|
Status int
|
||||||
Data interface{}
|
Data interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Auth(c *gin.Context) {
|
func Auth(c *gin.Context) {
|
||||||
var resp RespBase
|
var resp RespBase
|
||||||
var statuscode int
|
var statuscode int
|
||||||
|
|
||||||
statuscode = 200
|
statuscode = 200
|
||||||
|
|
||||||
var userinfo map[string] interface{}
|
var userinfo map[string]interface{}
|
||||||
//var userSockToken map[string] interface{}
|
//var userSockToken map[string] interface{}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -56,19 +56,20 @@ func Auth(c *gin.Context) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
socketToken := c.Query("socketToken")
|
socketToken := c.Query("socketToken")
|
||||||
struserinfo ,e := redis.Get(socketToken)
|
struserinfo, e := redis.Get(socketToken)
|
||||||
|
|
||||||
if e != nil{
|
if e != nil {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
e = json.Unmarshal([]byte(struserinfo),userinfo)
|
e = json.Unmarshal([]byte(struserinfo), userinfo)
|
||||||
if nil != e{
|
if nil != e {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetUser godoc
|
// SetUser godoc
|
||||||
// @Summary SetUser
|
// @Summary SetUser
|
||||||
// @Description set userinfo
|
// @Description set userinfo
|
||||||
|
@ -77,10 +78,10 @@ func Auth(c *gin.Context) {
|
||||||
// @Param q query string false "name search by q"
|
// @Param q query string false "name search by q"
|
||||||
// @Success 200 {array} util.RespBase
|
// @Success 200 {array} util.RespBase
|
||||||
// @Router /accounts [get]
|
// @Router /accounts [get]
|
||||||
func SetUser(c *gin.Context){
|
func SetUser(c *gin.Context) {
|
||||||
|
|
||||||
}
|
}
|
||||||
func DelUser(c *gin.Context){
|
func DelUser(c *gin.Context) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,25 +90,26 @@ func GetUser(c *gin.Context) {
|
||||||
resp.Msg = "操作失败"
|
resp.Msg = "操作失败"
|
||||||
resp.Status = 20
|
resp.Status = 20
|
||||||
defer func() {
|
defer func() {
|
||||||
c.JSON(200,resp)
|
c.JSON(200, resp)
|
||||||
}()
|
}()
|
||||||
session := sessions.Get(c)
|
session := sessions.Get(c)
|
||||||
userinfo := session.Get("")
|
userinfo := session.Get("")
|
||||||
if userinfo == nil{
|
if userinfo == nil {
|
||||||
logs.Error("error could not find key")
|
logs.Error("error could not find key")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var users map[string] interface{}
|
var users map[string]interface{}
|
||||||
e := json.Unmarshal([]byte(userinfo.(string)),&users)
|
e := json.Unmarshal([]byte(userinfo.(string)), &users)
|
||||||
if nil != e {
|
if nil != e {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
}
|
}
|
||||||
delete(users,"socketToken" +
|
delete(users, "socketToken"+
|
||||||
"")
|
"")
|
||||||
resp.Status = 0
|
resp.Status = 0
|
||||||
resp.Msg = "操作成功"
|
resp.Msg = "操作成功"
|
||||||
resp.Data = users
|
resp.Data = users
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUsers godoc
|
// GetUsers godoc
|
||||||
// @Summary GetUsers
|
// @Summary GetUsers
|
||||||
// @Description Get all user with query
|
// @Description Get all user with query
|
||||||
|
@ -127,23 +129,23 @@ func Users(c *gin.Context) {
|
||||||
resp.Status = 0
|
resp.Status = 0
|
||||||
statuscode = 200
|
statuscode = 200
|
||||||
defer func() {
|
defer func() {
|
||||||
c.JSON(statuscode,resp)
|
c.JSON(statuscode, resp)
|
||||||
}()
|
}()
|
||||||
offset := c.Query("offset")
|
offset := c.Query("offset")
|
||||||
limit := c.Query("limit")
|
limit := c.Query("limit")
|
||||||
ioffset,e := strconv.Atoi(offset)
|
ioffset, e := strconv.Atoi(offset)
|
||||||
if nil != e{
|
if nil != e {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ilimit,er := strconv.Atoi(limit)
|
ilimit, er := strconv.Atoi(limit)
|
||||||
if nil != er{
|
if nil != er {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dat := map[string] interface{}{}
|
dat := map[string]interface{}{}
|
||||||
users,all := model.GetUsers(int32(ilimit),int32(ioffset),"")
|
users, all := model.GetUsers(int32(ilimit), int32(ioffset), "")
|
||||||
dat["users"] = users
|
dat["users"] = users
|
||||||
dat["all"] = all
|
dat["all"] = all
|
||||||
resp.Msg = "OK"
|
resp.Msg = "OK"
|
||||||
|
@ -169,70 +171,72 @@ func SerarchUsers(c *gin.Context) {
|
||||||
resp.Status = 0
|
resp.Status = 0
|
||||||
statuscode = 200
|
statuscode = 200
|
||||||
defer func() {
|
defer func() {
|
||||||
c.JSON(statuscode,resp)
|
c.JSON(statuscode, resp)
|
||||||
}()
|
}()
|
||||||
offset := c.Query("offset")
|
offset := c.Query("offset")
|
||||||
limit := c.Query("limit")
|
limit := c.Query("limit")
|
||||||
username := c.PostForm("username")
|
username := c.PostForm("username")
|
||||||
ioffset,e := strconv.Atoi(offset)
|
ioffset, e := strconv.Atoi(offset)
|
||||||
if nil != e{
|
if nil != e {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ilimit,er := strconv.Atoi(limit)
|
ilimit, er := strconv.Atoi(limit)
|
||||||
if nil != er{
|
if nil != er {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dat := map[string] interface{}{}
|
dat := map[string]interface{}{}
|
||||||
users,all := model.GetUsers(int32(ilimit),int32(ioffset),username)
|
users, all := model.GetUsers(int32(ilimit), int32(ioffset), username)
|
||||||
dat["users"] = users
|
dat["users"] = users
|
||||||
dat["all"] = all
|
dat["all"] = all
|
||||||
resp.Msg = "OK"
|
resp.Msg = "OK"
|
||||||
resp.Data = dat
|
resp.Data = dat
|
||||||
}
|
}
|
||||||
func CreateVerify(length int32) string{
|
func CreateVerify(length int32) string {
|
||||||
strAry := []byte{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
strAry := []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}
|
||||||
result := string("")
|
result := string("")
|
||||||
for i := int32(0); i < length; i++ {
|
for i := int32(0); i < length; i++ {
|
||||||
x := rand.Intn(len(strAry))
|
|
||||||
result += string(strAry[x])
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 取随机Token
|
|
||||||
* @param {Number} length 取Token的长度
|
|
||||||
* @return {string} 获取的Token
|
|
||||||
*/
|
|
||||||
func createToken(length int32) string{
|
|
||||||
strAry := []byte{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_' };
|
|
||||||
result := string("")
|
|
||||||
for i := int32(0); i < length; i++ {
|
|
||||||
x := rand.Intn(len(strAry))
|
x := rand.Intn(len(strAry))
|
||||||
result += string(strAry[x])
|
result += string(strAry[x])
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func ByteSliceToString(b []byte) string {
|
/**
|
||||||
|
* 取随机Token
|
||||||
|
* @param {Number} length 取Token的长度
|
||||||
|
* @return {string} 获取的Token
|
||||||
|
*/
|
||||||
|
func createToken(length int32) string {
|
||||||
|
strAry := []byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '_'}
|
||||||
|
result := string("")
|
||||||
|
for i := int32(0); i < length; i++ {
|
||||||
|
x := rand.Intn(len(strAry))
|
||||||
|
result += string(strAry[x])
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func ByteSliceToString(b []byte) string {
|
||||||
var ret string
|
var ret string
|
||||||
|
|
||||||
for i := 0;i < len(b) ;i++{
|
for i := 0; i < len(b); i++ {
|
||||||
s := fmt.Sprintf("%02x",b[i])
|
s := fmt.Sprintf("%02x", b[i])
|
||||||
ret += string(s)
|
ret += string(s)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultOption(c *gin.Context) {
|
func DefaultOption(c *gin.Context) {
|
||||||
var resp RespBase
|
var resp RespBase
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
c.JSON(204, resp)
|
c.JSON(204, resp)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Login godoc
|
// Login godoc
|
||||||
// @Summary Login
|
// @Summary Login
|
||||||
// @Description login
|
// @Description login
|
||||||
|
@ -244,11 +248,11 @@ func DefaultOption(c *gin.Context) {
|
||||||
// @Failure 404 {object} util.RespBase
|
// @Failure 404 {object} util.RespBase
|
||||||
// @Failure 500 {object} util.RespBase
|
// @Failure 500 {object} util.RespBase
|
||||||
// @Router /api/login [post]
|
// @Router /api/login [post]
|
||||||
func Login(c *gin.Context) {
|
func Login(c *gin.Context) {
|
||||||
type LoginReq struct {
|
type LoginReq struct {
|
||||||
RememberMe int32 `json:"remember_me"`
|
RememberMe int32 `json:"remember_me"`
|
||||||
UserName string `json:"user_name"`
|
UserName string `json:"user_name"`
|
||||||
UserPwd string `json:"user_pwd"`
|
UserPwd string `json:"user_pwd"`
|
||||||
}
|
}
|
||||||
var req LoginReq
|
var req LoginReq
|
||||||
statusCode := 200
|
statusCode := 200
|
||||||
|
@ -258,7 +262,7 @@ func Login(c *gin.Context) {
|
||||||
c.JSON(statusCode, resp)
|
c.JSON(statusCode, resp)
|
||||||
}()
|
}()
|
||||||
e := c.Bind(&req)
|
e := c.Bind(&req)
|
||||||
if e!= nil{
|
if e != nil {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -269,8 +273,8 @@ func Login(c *gin.Context) {
|
||||||
var result []model.Users
|
var result []model.Users
|
||||||
|
|
||||||
er := db.GetMysqlClient().Query2("select * from users where user_name = ?",
|
er := db.GetMysqlClient().Query2("select * from users where user_name = ?",
|
||||||
&result,req.UserName)
|
&result, req.UserName)
|
||||||
if nil != er{
|
if nil != er {
|
||||||
log.Println(er.Error())
|
log.Println(er.Error())
|
||||||
}
|
}
|
||||||
strpassmd5 := ByteSliceToString(passmd5)
|
strpassmd5 := ByteSliceToString(passmd5)
|
||||||
|
@ -280,26 +284,26 @@ func Login(c *gin.Context) {
|
||||||
socketToken.Write([]byte(createToken(6))) // 需要加密的字符串为 123456
|
socketToken.Write([]byte(createToken(6))) // 需要加密的字符串为 123456
|
||||||
socketTokenMd5 := socketToken.Sum(nil)
|
socketTokenMd5 := socketToken.Sum(nil)
|
||||||
m := structs.Map(result[0])
|
m := structs.Map(result[0])
|
||||||
m["socketToken"] = ByteSliceToString(socketTokenMd5);
|
m["socketToken"] = ByteSliceToString(socketTokenMd5)
|
||||||
sessionInfo,err := json.Marshal(m)
|
sessionInfo, err := json.Marshal(m)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
log.Println(err.Error())
|
log.Println(err.Error())
|
||||||
}
|
}
|
||||||
if req.RememberMe == 1{
|
if req.RememberMe == 1 {
|
||||||
config.RedisOne().Set(string(socketTokenMd5),string(sessionInfo),time.Second *2 * 24 * 3600 * 1000 )
|
config.RedisOne().Set(string(socketTokenMd5), string(sessionInfo), time.Second*2*24*3600*1000)
|
||||||
}else {
|
} else {
|
||||||
config.RedisOne().Set(string(socketTokenMd5),string(sessionInfo),time.Second *8 * 3600 * 1000 )
|
config.RedisOne().Set(string(socketTokenMd5), string(sessionInfo), time.Second*8*3600*1000)
|
||||||
}
|
}
|
||||||
//存储session
|
//存储session
|
||||||
session := sessions.Get(c)
|
session := sessions.Get(c)
|
||||||
session.Set("",string(sessionInfo))
|
session.Set("", string(sessionInfo))
|
||||||
//session.
|
//session.
|
||||||
var Options *sessions.Options
|
var Options *sessions.Options
|
||||||
if req.RememberMe == 1{
|
if req.RememberMe == 1 {
|
||||||
Options = &sessions.Options{
|
Options = &sessions.Options{
|
||||||
MaxAge: 2 * 24 * 3600 * 1000,
|
MaxAge: 2 * 24 * 3600 * 1000,
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
Options = &sessions.Options{
|
Options = &sessions.Options{
|
||||||
MaxAge: 8 * 3600 * 1000,
|
MaxAge: 8 * 3600 * 1000,
|
||||||
}
|
}
|
||||||
|
@ -310,23 +314,23 @@ func Login(c *gin.Context) {
|
||||||
resp.Msg = "登录成功"
|
resp.Msg = "登录成功"
|
||||||
resp.Status = 0
|
resp.Status = 0
|
||||||
resp.Data = string(sessionInfo)
|
resp.Data = string(sessionInfo)
|
||||||
}else {
|
} else {
|
||||||
resp.Status = 422
|
resp.Status = 422
|
||||||
resp.Msg = "用户密码不正确"
|
resp.Msg = "用户密码不正确"
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
resp.Status = 422
|
resp.Status = 422
|
||||||
resp.Msg = "登录账号不存在,请重新输入"
|
resp.Msg = "登录账号不存在,请重新输入"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Register(c *gin.Context) {
|
func Register(c *gin.Context) {
|
||||||
type RegisterReq struct {
|
type RegisterReq struct {
|
||||||
DisplayName string `json:"display_name"`
|
DisplayName string `json:"display_name"`
|
||||||
EmailAdress string `json:"email_address"`
|
EmailAdress string `json:"email_address"`
|
||||||
EmailCode string `json:"email_code"`
|
EmailCode string `json:"email_code"`
|
||||||
UserName string `json:"user_name"`
|
UserName string `json:"user_name"`
|
||||||
UserPwd string `json:"user_pwd"`
|
UserPwd string `json:"user_pwd"`
|
||||||
}
|
}
|
||||||
var req RegisterReq
|
var req RegisterReq
|
||||||
statusCode := 200
|
statusCode := 200
|
||||||
|
@ -341,14 +345,14 @@ func Register(c *gin.Context) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
e := c.Bind(&req)
|
e := c.Bind(&req)
|
||||||
if e!= nil{
|
if e != nil {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
userKey := fmt.Sprintf("user_%s_verify",req.EmailAdress)
|
userKey := fmt.Sprintf("user_%s_verify", req.EmailAdress)
|
||||||
verify := config.RedisOne().Get(userKey).Val()
|
verify := config.RedisOne().Get(userKey).Val()
|
||||||
|
|
||||||
if verify != req.EmailCode{
|
if verify != req.EmailCode {
|
||||||
resp.Msg = "验证码错误"
|
resp.Msg = "验证码错误"
|
||||||
resp.Status = 20
|
resp.Status = 20
|
||||||
return
|
return
|
||||||
|
@ -369,28 +373,28 @@ func Register(c *gin.Context) {
|
||||||
var result []model.Users
|
var result []model.Users
|
||||||
|
|
||||||
er := db.GetMysqlClient().Query2("select * from users where user_name = ?",
|
er := db.GetMysqlClient().Query2("select * from users where user_name = ?",
|
||||||
&result,req.UserName)
|
&result, req.UserName)
|
||||||
if nil != er{
|
if nil != er {
|
||||||
log.Println(er.Error())
|
log.Println(er.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(result) > 0{
|
if len(result) > 0 {
|
||||||
resp.Msg = "失败,账号已经存在"
|
resp.Msg = "失败,账号已经存在"
|
||||||
resp.Status = 20
|
resp.Status = 20
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
query := fmt.Sprintf("insert into users(user_name,user_pwd,created_date," +
|
query := fmt.Sprintf("insert into users(user_name,user_pwd,created_date,"+
|
||||||
"updated_date,display_name,email_address) values ('%s','%s','%s','%s','%s','%s') ",user.UserName,user.UserPwd,user.CreatedDate,user.UpdatedDate,
|
"updated_date,display_name,email_address) values ('%s','%s','%s','%s','%s','%s') ", user.UserName, user.UserPwd, user.CreatedDate, user.UpdatedDate,
|
||||||
user.DisplayName,user.EmailAddress)
|
user.DisplayName, user.EmailAddress)
|
||||||
n,er := db.GetMysqlClient().Insert(query)
|
n, er := db.GetMysqlClient().Insert(query)
|
||||||
if n == 0 || n < 0{
|
if n == 0 || n < 0 {
|
||||||
statusCode = 422
|
statusCode = 422
|
||||||
logs.Error(er.Error())
|
logs.Error(er.Error())
|
||||||
resp.Msg = "失败,账号已经存在"
|
resp.Msg = "失败,账号已经存在"
|
||||||
resp.Status = 20
|
resp.Status = 20
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if nil != er{
|
if nil != er {
|
||||||
statusCode = 422
|
statusCode = 422
|
||||||
logs.Error(er.Error())
|
logs.Error(er.Error())
|
||||||
resp.Msg = "失败"
|
resp.Msg = "失败"
|
||||||
|
@ -401,65 +405,64 @@ func Register(c *gin.Context) {
|
||||||
resp.Status = 0
|
resp.Status = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func Logout(c *gin.Context) {
|
func Logout(c *gin.Context) {
|
||||||
var resp RespBase
|
var resp RespBase
|
||||||
|
|
||||||
resp.Msg = "退出成功"
|
resp.Msg = "退出成功"
|
||||||
resp.Status = 0
|
resp.Status = 0
|
||||||
defer func() {
|
defer func() {
|
||||||
c.JSON(200,resp)
|
c.JSON(200, resp)
|
||||||
}()
|
}()
|
||||||
session := sessions.Get(c)
|
session := sessions.Get(c)
|
||||||
session.Delete("")
|
session.Delete("")
|
||||||
session.Save()
|
session.Save()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Reader2Json(r io.ReadCloser) string {
|
||||||
func Reader2Json(r io.ReadCloser) string{
|
|
||||||
var ret string
|
var ret string
|
||||||
for i := 0;;i++{
|
for i := 0; ; i++ {
|
||||||
s := make([]byte,10)
|
s := make([]byte, 10)
|
||||||
_,e := r.Read(s)
|
_, e := r.Read(s)
|
||||||
ret += string(s)
|
ret += string(s)
|
||||||
if e != nil{
|
if e != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendExternalEmail(msg interface{}) error{
|
func SendExternalEmail(msg interface{}) error {
|
||||||
req := make(map[string] interface{},1)
|
req := make(map[string]interface{}, 1)
|
||||||
req["type"] = "text"
|
req["type"] = "text"
|
||||||
req["action"] = "smtp-sys"
|
req["action"] = "smtp-sys"
|
||||||
req["apiType"] = "send"
|
req["apiType"] = "send"
|
||||||
|
|
||||||
content ,err := json.Marshal(msg)
|
content, err := json.Marshal(msg)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
log.Println(err.Error())
|
log.Println(err.Error())
|
||||||
return errors.New("Json marshal error")
|
return errors.New("Json marshal error")
|
||||||
}
|
}
|
||||||
req["content"] = string(content)
|
req["content"] = string(content)
|
||||||
|
|
||||||
var buffer bytes.Buffer
|
var buffer bytes.Buffer
|
||||||
b,e := json.Marshal(req)
|
b, e := json.Marshal(req)
|
||||||
if e != nil{
|
if e != nil {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
}
|
}
|
||||||
buffer.Write(b)
|
buffer.Write(b)
|
||||||
resp,err := http.Post("http://47.93.230.163:8091/msg/v1/send","application/json",&buffer)
|
resp, err := http.Post("http://47.93.230.163:8091/msg/v1/send", "application/json", &buffer)
|
||||||
|
|
||||||
if resp.StatusCode != 200{
|
if resp.StatusCode != 200 {
|
||||||
return errors.New("error send emain")
|
return errors.New("error send emain")
|
||||||
}
|
}
|
||||||
if err != nil{
|
if err != nil {
|
||||||
logs.Error("error send email")
|
logs.Error("error send email")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendToMail(title,user string, password string, host string, to string, content string,
|
func SendToMail(title, user string, password string, host string, to string, content string,
|
||||||
ifgenerate bool) error {
|
ifgenerate bool) error {
|
||||||
var content_type string
|
var content_type string
|
||||||
|
|
||||||
|
@ -469,26 +472,26 @@ func SendToMail(title,user string, password string, host string, to string, cont
|
||||||
content_type = "Content-Type: text/plain" + "; charset=UTF-8"
|
content_type = "Content-Type: text/plain" + "; charset=UTF-8"
|
||||||
|
|
||||||
msg := []byte("To: " + to + "\r\nFrom: " + user + "\r\nSubject: " + title + "\r\n" +
|
msg := []byte("To: " + to + "\r\nFrom: " + user + "\r\nSubject: " + title + "\r\n" +
|
||||||
content_type + "\r\n\r\n"+ content + "\r\n" )
|
content_type + "\r\n\r\n" + content + "\r\n")
|
||||||
send_to := strings.Split(to, ";")
|
send_to := strings.Split(to, ";")
|
||||||
|
|
||||||
//检测是否是邮件地址
|
//检测是否是邮件地址
|
||||||
for k,_ := range send_to{
|
for k, _ := range send_to {
|
||||||
match, _ := regexp.MatchString("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?", send_to[k])
|
match, _ := regexp.MatchString("[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?", send_to[k])
|
||||||
if !match{
|
if !match {
|
||||||
return errors.New("Format Error")
|
return errors.New("Format Error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := smtp.SendMail(host, auth, user,send_to, msg)
|
err := smtp.SendMail(host, auth, user, send_to, msg)
|
||||||
if err !=nil{
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendEmailCode(c *gin.Context) {
|
func SendEmailCode(c *gin.Context) {
|
||||||
var req ReqSendEmailCode
|
var req ReqSendEmailCode
|
||||||
var resp RespBase = RespBase{Msg:"邮件已经存在",Status:0}
|
var resp RespBase = RespBase{Msg: "邮件已经存在", Status: 0}
|
||||||
statusCode := 200
|
statusCode := 200
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -496,31 +499,31 @@ func SendEmailCode(c *gin.Context) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
e := c.Bind(&req)
|
e := c.Bind(&req)
|
||||||
if nil != e{
|
if nil != e {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
resp.Msg = "请求参数错误"
|
resp.Msg = "请求参数错误"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//判断邮箱是否存在
|
//判断邮箱是否存在
|
||||||
var users []model.Users
|
var users []model.Users
|
||||||
db.GetMysqlClient().Query2("select * from users where email_adress = ?",&users,req.EmailAdress)
|
db.GetMysqlClient().Query2("select * from users where email_adress = ?", &users, req.EmailAdress)
|
||||||
if len(users) != 0{
|
if len(users) != 0 {
|
||||||
statusCode = 422
|
statusCode = 422
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//产生验证码
|
//产生验证码
|
||||||
verify := CreateVerify(6)
|
verify := CreateVerify(6)
|
||||||
session := sessions.Get(c)
|
session := sessions.Get(c)
|
||||||
session.Set(req.EmailAdress,verify)
|
session.Set(req.EmailAdress, verify)
|
||||||
|
|
||||||
session.Save()
|
session.Save()
|
||||||
sendcontent := make( map[string] interface{},1)
|
sendcontent := make(map[string]interface{}, 1)
|
||||||
sendcontent["subject"] = "邮箱验证码,请注意查收"
|
sendcontent["subject"] = "邮箱验证码,请注意查收"
|
||||||
sendcontent["receivers"] = req.EmailAdress
|
sendcontent["receivers"] = req.EmailAdress
|
||||||
sendcontent["content"] = string("您本次注册的验证码为:") + verify + string(",工作人员不会向您索取,请勿泄露。请尽快完成操作。")
|
sendcontent["content"] = string("您本次注册的验证码为:") + verify + string(",工作人员不会向您索取,请勿泄露。请尽快完成操作。")
|
||||||
|
|
||||||
e = SendExternalEmail(sendcontent)
|
e = SendExternalEmail(sendcontent)
|
||||||
if e != nil{
|
if e != nil {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
"user/controller"
|
|
||||||
"user/config"
|
"user/config"
|
||||||
|
"user/controller"
|
||||||
"user/db"
|
"user/db"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -63,9 +63,10 @@ type ReqSendEmailTpl struct {
|
||||||
Generate bool `json:"generate"`
|
Generate bool `json:"generate"`
|
||||||
}
|
}
|
||||||
type ReqSendEmail struct {
|
type ReqSendEmail struct {
|
||||||
Email string `json:"email_address"`
|
Email string `json:"email_address"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendToMail(title, user, password, host, to, content string) error {
|
func SendToMail(title, user, password, host, to, content string) error {
|
||||||
var content_type string
|
var content_type string
|
||||||
hp := strings.Split(host, ":")
|
hp := strings.Split(host, ":")
|
||||||
|
@ -90,7 +91,6 @@ func SendToMail(title, user, password, host, to, content string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func SendToMailTpl(title, user, password, host, to, tplname string, content interface{}, mailtype string, ifgenerate bool) error {
|
func SendToMailTpl(title, user, password, host, to, tplname string, content interface{}, mailtype string, ifgenerate bool) error {
|
||||||
var content_type string
|
var content_type string
|
||||||
var paseresult bytes.Buffer
|
var paseresult bytes.Buffer
|
||||||
|
@ -248,18 +248,18 @@ func OnSendEmailCode(c *gin.Context) {
|
||||||
resp.Msg = "ParaErr"
|
resp.Msg = "ParaErr"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.Email != ""{
|
if req.Email != "" {
|
||||||
type Count struct {
|
type Count struct {
|
||||||
Count int32 `json:"count"`
|
Count int32 `json:"count"`
|
||||||
}
|
}
|
||||||
cnt := []Count{}
|
cnt := []Count{}
|
||||||
query := fmt.Sprintf("select count(*) as count from users where users.email_address = %s",req.Email)
|
query := fmt.Sprintf("select count(*) as count from users where users.email_address = %s", req.Email)
|
||||||
e := db.GetMysqlClient().Query2(query,&cnt)
|
e := db.GetMysqlClient().Query2(query, &cnt)
|
||||||
if nil !=e {
|
if nil != e {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}else {
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user := "c7458969@163.com"
|
user := "c7458969@163.com"
|
||||||
|
@ -270,8 +270,8 @@ func OnSendEmailCode(c *gin.Context) {
|
||||||
//发送
|
//发送
|
||||||
verCode := controller.CreateVerify(6)
|
verCode := controller.CreateVerify(6)
|
||||||
content := "您的验证码是" + verCode
|
content := "您的验证码是" + verCode
|
||||||
userKey := fmt.Sprintf("user_%s_verify",req.Email)
|
userKey := fmt.Sprintf("user_%s_verify", req.Email)
|
||||||
config.RedisOne().Set(userKey,verCode,time.Hour * 24)
|
config.RedisOne().Set(userKey, verCode, time.Hour*24)
|
||||||
e = SendToMail("后台管理系统验证码", user, password, host, req.Email, content)
|
e = SendToMail("后台管理系统验证码", user, password, host, req.Email, content)
|
||||||
if nil != e {
|
if nil != e {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
|
|
81
db/db.go
81
db/db.go
|
@ -15,7 +15,7 @@ import (
|
||||||
// 数据容器抽象对象定义
|
// 数据容器抽象对象定义
|
||||||
type Database struct {
|
type Database struct {
|
||||||
Type string // 用来给SqlBuilder进行一些特殊的判断 (空值或mysql 皆表示这是一个MySQL实例)
|
Type string // 用来给SqlBuilder进行一些特殊的判断 (空值或mysql 皆表示这是一个MySQL实例)
|
||||||
DB *sql.DB
|
DB *sql.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQL异步执行队列定义
|
// SQL异步执行队列定义
|
||||||
|
@ -231,14 +231,14 @@ func (this *Database) queryAndReflect(sql string,
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
if nil != row[i] {
|
if nil != row[i] {
|
||||||
//log.Println(row[i].(float32))
|
//log.Println(row[i].(float32))
|
||||||
switch reflect.TypeOf(row[i]).Kind(){
|
switch reflect.TypeOf(row[i]).Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
v, e := strconv.ParseFloat(string(row[i].([]byte)), 0)
|
v, e := strconv.ParseFloat(string(row[i].([]byte)), 0)
|
||||||
if nil == e {
|
if nil == e {
|
||||||
feild.Field(n).SetFloat(float64(v))
|
feild.Field(n).SetFloat(float64(v))
|
||||||
//feild.Field(n).SetFloat(float64(row[i].(float32)))
|
//feild.Field(n).SetFloat(float64(row[i].(float32)))
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
feild.Field(n).SetFloat(float64(row[i].(float32)))
|
feild.Field(n).SetFloat(float64(row[i].(float32)))
|
||||||
}
|
}
|
||||||
|
@ -312,59 +312,59 @@ func (this *Database) Delete(query string, args ...interface{}) (int64, error) {
|
||||||
return this.Update(query, args...)
|
return this.Update(query, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenSql(obj interface{}) (string,error) {
|
func GenSql(obj interface{}) (string, error) {
|
||||||
ret := ""
|
ret := ""
|
||||||
typ := reflect.TypeOf(obj).Kind()
|
typ := reflect.TypeOf(obj).Kind()
|
||||||
if typ != reflect.Struct{
|
if typ != reflect.Struct {
|
||||||
return (""),errors.New("not a struct")
|
return (""), errors.New("not a struct")
|
||||||
}
|
}
|
||||||
value := obj.(reflect.Value)
|
value := obj.(reflect.Value)
|
||||||
num := value.NumField()
|
num := value.NumField()
|
||||||
for i := 0;i < num;i++{
|
for i := 0; i < num; i++ {
|
||||||
if i == 0{
|
if i == 0 {
|
||||||
ret += "("
|
ret += "("
|
||||||
}
|
}
|
||||||
switch (value.Field(i).Type().Kind()){
|
switch value.Field(i).Type().Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
str := value.Field(i).Interface().(string)
|
str := value.Field(i).Interface().(string)
|
||||||
if str[0] != '"'{
|
if str[0] != '"' {
|
||||||
ret += "\""
|
ret += "\""
|
||||||
str += "\""
|
str += "\""
|
||||||
ret += str
|
ret += str
|
||||||
|
|
||||||
}else{
|
} else {
|
||||||
ret += value.Field(i).Interface().(string)
|
ret += value.Field(i).Interface().(string)
|
||||||
}
|
}
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
ret += fmt.Sprintf("%d",value.Field(i).Interface().(int))
|
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int))
|
||||||
case reflect.Int8:
|
case reflect.Int8:
|
||||||
ret += fmt.Sprintf("%d",value.Field(i).Interface().(int8))
|
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int8))
|
||||||
case reflect.Int32:
|
case reflect.Int32:
|
||||||
ret += fmt.Sprintf("%d",value.Field(i).Interface().(int32))
|
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int32))
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
ret += fmt.Sprintf("%d",value.Field(i).Interface().(int64))
|
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int64))
|
||||||
case reflect.Int16:
|
case reflect.Int16:
|
||||||
ret += fmt.Sprintf("%d",value.Field(i).Interface().(int16))
|
ret += fmt.Sprintf("%d", value.Field(i).Interface().(int16))
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
if value.Field(i).Interface().(bool) {
|
if value.Field(i).Interface().(bool) {
|
||||||
ret += fmt.Sprintf("true",)
|
ret += fmt.Sprintf("true")
|
||||||
}else {
|
} else {
|
||||||
ret += fmt.Sprintf("false",)
|
ret += fmt.Sprintf("false")
|
||||||
}
|
}
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
ret += fmt.Sprintf("%x",value.Field(i).Interface().(float32))
|
ret += fmt.Sprintf("%x", value.Field(i).Interface().(float32))
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
ret += fmt.Sprintf("true",value.Field(i).Interface().(float64))
|
ret += fmt.Sprintf("true", value.Field(i).Interface().(float64))
|
||||||
}
|
}
|
||||||
if i == num - 1{
|
if i == num-1 {
|
||||||
ret += ")"
|
ret += ")"
|
||||||
}else {
|
} else {
|
||||||
ret += ","
|
ret += ","
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret,nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
func (this *Database) InsertObejct(tb_name string,obj interface{}) (int64,error) {
|
func (this *Database) InsertObejct(tb_name string, obj interface{}) (int64, error) {
|
||||||
var tagMap map[int]string
|
var tagMap map[int]string
|
||||||
var tp, tps reflect.Type
|
var tp, tps reflect.Type
|
||||||
var n, i int
|
var n, i int
|
||||||
|
@ -372,11 +372,11 @@ func (this *Database) InsertObejct(tb_name string,obj interface{}) (int64,error)
|
||||||
// 检测val参数是否为我们所想要的参数
|
// 检测val参数是否为我们所想要的参数
|
||||||
tp = reflect.TypeOf(obj)
|
tp = reflect.TypeOf(obj)
|
||||||
if reflect.Ptr != tp.Kind() {
|
if reflect.Ptr != tp.Kind() {
|
||||||
return 0,errors.New("is not pointer")
|
return 0, errors.New("is not pointer")
|
||||||
}
|
}
|
||||||
|
|
||||||
if reflect.Slice != tp.Elem().Kind() {
|
if reflect.Slice != tp.Elem().Kind() {
|
||||||
return 0,errors.New("is not slice pointer")
|
return 0, errors.New("is not slice pointer")
|
||||||
}
|
}
|
||||||
|
|
||||||
tp = tp.Elem()
|
tp = tp.Elem()
|
||||||
|
@ -384,9 +384,9 @@ func (this *Database) InsertObejct(tb_name string,obj interface{}) (int64,error)
|
||||||
value := reflect.ValueOf(obj).Elem()
|
value := reflect.ValueOf(obj).Elem()
|
||||||
|
|
||||||
if reflect.Struct != tps.Kind() {
|
if reflect.Struct != tps.Kind() {
|
||||||
return 0,errors.New("is not struct slice pointer")
|
return 0, errors.New("is not struct slice pointer")
|
||||||
}
|
}
|
||||||
for z := 0; z < value.Len();z ++ {
|
for z := 0; z < value.Len(); z++ {
|
||||||
tagMap = make(map[int]string)
|
tagMap = make(map[int]string)
|
||||||
n = tps.NumField()
|
n = tps.NumField()
|
||||||
var query_struct string
|
var query_struct string
|
||||||
|
@ -395,28 +395,29 @@ func (this *Database) InsertObejct(tb_name string,obj interface{}) (int64,error)
|
||||||
if len(tag) > 0 {
|
if len(tag) > 0 {
|
||||||
tagMap[i] = tag
|
tagMap[i] = tag
|
||||||
}
|
}
|
||||||
if i == 0{
|
if i == 0 {
|
||||||
query_struct += "("
|
query_struct += "("
|
||||||
}
|
}
|
||||||
query_struct += tagMap[i]
|
query_struct += tagMap[i]
|
||||||
if i == n -1{
|
if i == n-1 {
|
||||||
query_struct += ")"
|
query_struct += ")"
|
||||||
}else {
|
} else {
|
||||||
query_struct += ","
|
query_struct += ","
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vs ,e := GenSql(value.Index(z))
|
vs, e := GenSql(value.Index(z))
|
||||||
if nil != e{
|
if nil != e {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
}
|
}
|
||||||
query := "insert into " + tb_name + query_struct + "values " + vs
|
query := "insert into " + tb_name + query_struct + "values " + vs
|
||||||
_, e = this.Insert(query)
|
_, e = this.Insert(query)
|
||||||
if e != nil{
|
if e != nil {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0,nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 执行INSERT语句并返回最后生成的自增ID
|
// 执行INSERT语句并返回最后生成的自增ID
|
||||||
// 返回0表示没有出错, 但没生成自增ID
|
// 返回0表示没有出错, 但没生成自增ID
|
||||||
// 返回-1表示出错
|
// 返回-1表示出错
|
||||||
|
|
12
db/mssql.go
12
db/mssql.go
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
// ProcExec 执行存储过程, 返回受影响的行数
|
// ProcExec 执行存储过程, 返回受影响的行数
|
||||||
func (this *Database) ExecProc(procname string, params ...interface{}) (int64, error) {
|
func (this *Database) ExecProc(procname string, params ...interface{}) (int64, error) {
|
||||||
result, err := this.Exec("EXEC " + procname + " " + this.GetProcPlaceholder(len(params)), params...)
|
result, err := this.Exec("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -33,20 +33,20 @@ func (this *Database) GetExecProcErr(procname string, params ...interface{}) err
|
||||||
|
|
||||||
// ProcQuery 通过存储过程查询记录
|
// ProcQuery 通过存储过程查询记录
|
||||||
func (this *Database) ProcQuery(procname string, params ...interface{}) (rows *sql.Rows, err error) {
|
func (this *Database) ProcQuery(procname string, params ...interface{}) (rows *sql.Rows, err error) {
|
||||||
rows, err = this.Query("EXEC " + procname + " " + this.GetProcPlaceholder(len(params)), params...)
|
rows, err = this.Query("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcQueryRow 通过存储过程查询单条记录
|
// ProcQueryRow 通过存储过程查询单条记录
|
||||||
func (this *Database) ProcQueryRow(procname string, params ...interface{}) *sql.Row {
|
func (this *Database) ProcQueryRow(procname string, params ...interface{}) *sql.Row {
|
||||||
return this.QueryRow("EXEC " + procname + " " + this.GetProcPlaceholder(len(params)), params...)
|
return this.QueryRow("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcStatus 调用存储过程并获取最终的执行状态码和提示信息
|
// ProcStatus 调用存储过程并获取最终的执行状态码和提示信息
|
||||||
func (this *Database) ProcStatus(procname string, params ...interface{}) (int, string) {
|
func (this *Database) ProcStatus(procname string, params ...interface{}) (int, string) {
|
||||||
var status int
|
var status int
|
||||||
var msg string
|
var msg string
|
||||||
err := this.QueryRow("EXEC " + procname + " " + this.GetProcPlaceholder(len(params)), params...).Scan(&status, &msg)
|
err := this.QueryRow("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...).Scan(&status, &msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -99, err.Error()
|
return -99, err.Error()
|
||||||
}
|
}
|
||||||
|
@ -55,12 +55,12 @@ func (this *Database) ProcStatus(procname string, params ...interface{}) (int, s
|
||||||
|
|
||||||
// ProcSelect 通过存储过程查询结果集
|
// ProcSelect 通过存储过程查询结果集
|
||||||
func (this *Database) ProcSelect(procname string, params ...interface{}) (Results, error) {
|
func (this *Database) ProcSelect(procname string, params ...interface{}) (Results, error) {
|
||||||
return this.Select("EXEC " + procname + " " + this.GetProcPlaceholder(len(params)), params...)
|
return this.Select("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProcSelectOne 通过存储查询一行不定字段的结果
|
// ProcSelectOne 通过存储查询一行不定字段的结果
|
||||||
func (this *Database) ProcSelectOne(procname string, params ...interface{}) (OneRow, error) {
|
func (this *Database) ProcSelectOne(procname string, params ...interface{}) (OneRow, error) {
|
||||||
return this.SelectOne("EXEC " + procname + " " + this.GetProcPlaceholder(len(params)), params...)
|
return this.SelectOne("EXEC "+procname+" "+this.GetProcPlaceholder(len(params)), params...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProcPlaceholder 按照指定数量生成调用存储过程时所用的参数占位符
|
// GetProcPlaceholder 按照指定数量生成调用存储过程时所用的参数占位符
|
||||||
|
|
|
@ -9,23 +9,21 @@ import (
|
||||||
|
|
||||||
var gDb Database
|
var gDb Database
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
mysqlconf := config.GetMysqlConfig()
|
mysqlconf := config.GetMysqlConfig()
|
||||||
cnn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8",mysqlconf.UserName,mysqlconf.Password,
|
cnn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8", mysqlconf.UserName, mysqlconf.Password,
|
||||||
mysqlconf.Addr,mysqlconf.Db)
|
mysqlconf.Addr, mysqlconf.Db)
|
||||||
_db,err := sql.Open("mysql",cnn)
|
_db, err := sql.Open("mysql", cnn)
|
||||||
if err != nil{
|
if err != nil {
|
||||||
fmt.Println("connect sql server ",err.Error())
|
fmt.Println("connect sql server ", err.Error())
|
||||||
}
|
}
|
||||||
e := _db.Ping()
|
e := _db.Ping()
|
||||||
if nil != e{
|
if nil != e {
|
||||||
fmt.Println(e.Error())
|
fmt.Println(e.Error())
|
||||||
}
|
}
|
||||||
gDb = Database{Type:string(""),DB:_db}
|
gDb = Database{Type: string(""), DB: _db}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetMysqlClient() *Database {
|
func GetMysqlClient() *Database {
|
||||||
return &gDb
|
return &gDb
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,18 +3,18 @@ package db
|
||||||
import (
|
import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"math/big"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"log"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"git.jiaxianghudong.com/go/utils"
|
"git.jiaxianghudong.com/go/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_ = iota
|
_ = iota
|
||||||
TYPE_INSERT
|
TYPE_INSERT
|
||||||
TYPE_DELETE
|
TYPE_DELETE
|
||||||
TYPE_UPDATE
|
TYPE_UPDATE
|
||||||
|
@ -24,31 +24,31 @@ const (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
WrapSymbol = "`"
|
WrapSymbol = "`"
|
||||||
DBType = "mysql"
|
DBType = "mysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SQL语句构造结构
|
// SQL语句构造结构
|
||||||
type SB struct {
|
type SB struct {
|
||||||
db *Database
|
db *Database
|
||||||
t int
|
t int
|
||||||
field, table, where, group, order, limit string
|
field, table, where, group, order, limit string
|
||||||
values SBValues
|
values SBValues
|
||||||
values2 SBValues
|
values2 SBValues
|
||||||
ignore bool
|
ignore bool
|
||||||
fullsql bool
|
fullsql bool
|
||||||
debug bool
|
debug bool
|
||||||
unsafe bool //是否进行安全检查, 专门针对无限定的UPDATE和DELETE进行二次验证
|
unsafe bool //是否进行安全检查, 专门针对无限定的UPDATE和DELETE进行二次验证
|
||||||
args []interface{}
|
args []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec返回结果
|
// Exec返回结果
|
||||||
type SBResult struct {
|
type SBResult struct {
|
||||||
Success bool //语句是否执行成功
|
Success bool //语句是否执行成功
|
||||||
Code int //错误代码
|
Code int //错误代码
|
||||||
Msg string //错误提示信息
|
Msg string //错误提示信息
|
||||||
LastID int64 //最后产生的ID
|
LastID int64 //最后产生的ID
|
||||||
Affected int64 //受影响的行数
|
Affected int64 //受影响的行数
|
||||||
Sql string //最后执行的SQL
|
Sql string //最后执行的SQL
|
||||||
}
|
}
|
||||||
|
|
||||||
// 值对象
|
// 值对象
|
||||||
|
@ -56,7 +56,7 @@ type SBValues map[string]interface{}
|
||||||
|
|
||||||
// 增量值
|
// 增量值
|
||||||
type IncVal struct {
|
type IncVal struct {
|
||||||
Val int64
|
Val int64
|
||||||
BaseField string // 为空表示对当前字段累加
|
BaseField string // 为空表示对当前字段累加
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,8 +473,8 @@ func (q *SB) Exec(args ...interface{}) *SBResult {
|
||||||
case TYPE_INSERT:
|
case TYPE_INSERT:
|
||||||
if DBType == "mysql" {
|
if DBType == "mysql" {
|
||||||
last, err := ret.LastInsertId()
|
last, err := ret.LastInsertId()
|
||||||
if (err == nil) {
|
if err == nil {
|
||||||
sbRet.LastID = last;
|
sbRet.LastID = last
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case TYPE_DELETE:
|
case TYPE_DELETE:
|
||||||
|
@ -483,7 +483,7 @@ func (q *SB) Exec(args ...interface{}) *SBResult {
|
||||||
fallthrough
|
fallthrough
|
||||||
case TYPE_INSERTUPDATE:
|
case TYPE_INSERTUPDATE:
|
||||||
aff, err := ret.RowsAffected()
|
aff, err := ret.RowsAffected()
|
||||||
if (err == nil) {
|
if err == nil {
|
||||||
sbRet.Affected = aff
|
sbRet.Affected = aff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"strconv"
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 根据传入的字段列表生成相符数量的占位符
|
// 根据传入的字段列表生成相符数量的占位符
|
||||||
|
@ -53,7 +53,7 @@ func NewNullString(s string) sql.NullString {
|
||||||
}
|
}
|
||||||
return sql.NullString{
|
return sql.NullString{
|
||||||
String: s,
|
String: s,
|
||||||
Valid: true,
|
Valid: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ func Error(err ...interface{}) {
|
||||||
func Waring(war ...interface{}) {
|
func Waring(war ...interface{}) {
|
||||||
log.write(LOG_WARING, fmt.Sprint(war...))
|
log.write(LOG_WARING, fmt.Sprint(war...))
|
||||||
}
|
}
|
||||||
func SetLevel(level int) {
|
func SetLevel(level int) {
|
||||||
log.setLevel(level)
|
log.setLevel(level)
|
||||||
}
|
}
|
||||||
func Info(info ...interface{}) {
|
func Info(info ...interface{}) {
|
||||||
|
|
50
main.go
50
main.go
|
@ -5,48 +5,47 @@ import (
|
||||||
"github.com/tommy351/gin-sessions"
|
"github.com/tommy351/gin-sessions"
|
||||||
"log"
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"user/controller"
|
|
||||||
"user/config"
|
"user/config"
|
||||||
|
"user/controller"
|
||||||
"user/controller/mail"
|
"user/controller/mail"
|
||||||
"user/db"
|
"user/db"
|
||||||
"user/logs"
|
"user/logs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitMysql() {
|
func InitMysql() {
|
||||||
c := config.GetMysqlConfig()
|
c := config.GetMysqlConfig()
|
||||||
if c == nil{
|
if c == nil {
|
||||||
logs.Error("cannnot connect mysql server")
|
logs.Error("cannnot connect mysql server")
|
||||||
}else {
|
} else {
|
||||||
db.Init()
|
db.Init()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func CORSMiddleware(c *gin.Context) {
|
func CORSMiddleware(c *gin.Context) {
|
||||||
ori := c.Request.Header.Get("Origin")
|
ori := c.Request.Header.Get("Origin")
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
|
c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, UPDATE")
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Origin",ori)
|
c.Writer.Header().Set("Access-Control-Allow-Origin", ori)
|
||||||
log.Println(c.Request.Header.Get("Origin"))
|
c.Writer.Header().Set("Access-Control-Max-Age", "86400")
|
||||||
c.Writer.Header().Set("Access-Control-Max-Age", "86400")
|
c.Writer.Header().Set("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding, x-access-token")
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding, x-access-token")
|
c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length")
|
||||||
c.Writer.Header().Set("Access-Control-Expose-Headers", "Content-Length")
|
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||||
c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
|
|
||||||
|
|
||||||
if c.Request.Method == "OPTIONS" {
|
if c.Request.Method == "OPTIONS" {
|
||||||
log.Println("OPTIONS")
|
log.Println("OPTIONS")
|
||||||
c.AbortWithStatus(200)
|
c.AbortWithStatus(200)
|
||||||
} else {
|
} else {
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
e := config.Init("user.yaml")
|
e := config.Init("user.yaml")
|
||||||
if nil != e{
|
if nil != e {
|
||||||
log.Println(e.Error())
|
log.Println(e.Error())
|
||||||
}
|
}
|
||||||
logs.Init(config.GetLogConfig().Dir,config.GetLogConfig().File,config.GetLogConfig().Level,config.GetLogConfig().SaveFile)
|
logs.Init(config.GetLogConfig().Dir, config.GetLogConfig().File, config.GetLogConfig().Level, config.GetLogConfig().SaveFile)
|
||||||
db.Init()
|
db.Init()
|
||||||
e = config.InitRedis()
|
e = config.InitRedis()
|
||||||
if nil != e{
|
if nil != e {
|
||||||
logs.Error(e.Error())
|
logs.Error(e.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -70,7 +69,10 @@ func main() {
|
||||||
r.POST("/api/register", controller.Register)
|
r.POST("/api/register", controller.Register)
|
||||||
/** 用户退出登陆 **/
|
/** 用户退出登陆 **/
|
||||||
r.GET("/api/logout", controller.Logout)
|
r.GET("/api/logout", controller.Logout)
|
||||||
r.POST("/api/verify",mail.OnSendEmailCode)
|
r.POST("/api/verify", mail.OnSendEmailCode)
|
||||||
|
}
|
||||||
|
e = r.Run(":" + strconv.Itoa(config.GetPort()))
|
||||||
|
if nil != e{
|
||||||
|
log.Print(e.Error())
|
||||||
}
|
}
|
||||||
r.Run(":" + strconv.Itoa(config.GetPort()))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,35 +2,35 @@ package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"qiniupkg.com/x/log.v7"
|
"log"
|
||||||
"user/db"
|
"user/db"
|
||||||
"user/logs"
|
"user/logs"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Users struct {
|
type Users struct {
|
||||||
ID int64 `sql:"id" json:"id"`
|
ID int64 `sql:"id" json:"id"`
|
||||||
UserName string `sql:"user_name" json:"user_name"`
|
UserName string `sql:"user_name" json:"user_name"`
|
||||||
UserPwd string `sql:"user_pwd" json:"-"`
|
UserPwd string `sql:"user_pwd" json:"-"`
|
||||||
CreatedDate string `sql:"created_date" json:"created_date"`
|
CreatedDate string `sql:"created_date" json:"created_date"`
|
||||||
UpdatedDate string `sql:"updated_date" json:"updated_date"`
|
UpdatedDate string `sql:"updated_date" json:"updated_date"`
|
||||||
DisplayName string `sql:"display_name" json:"display_name"`
|
DisplayName string `sql:"display_name" json:"display_name"`
|
||||||
EmailAddress string `sql:"email_address" json:"email_address"`
|
EmailAddress string `sql:"email_address" json:"email_address"`
|
||||||
Tel string `sql:"tel" json:"tel"`
|
Tel string `sql:"tel" json:"tel"`
|
||||||
Avatar string `sql:"avatar" json:"avatar"`
|
Avatar string `sql:"avatar" json:"avatar"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUsers(limit int32,offsetPage int32,name string) ([]Users,int32){
|
func GetUsers(limit int32, offsetPage int32, name string) ([]Users, int32) {
|
||||||
users := []Users{}
|
users := []Users{}
|
||||||
var query string
|
var query string
|
||||||
if name != ""{
|
if name != "" {
|
||||||
log.Println(name)
|
log.Println(name)
|
||||||
query = fmt.Sprintf("select * from users where user_name like '%s' limit %d offset %d","%%" + name + "%%",limit,offsetPage*limit)
|
query = fmt.Sprintf("select * from users where user_name like '%s' limit %d offset %d", "%%"+name+"%%", limit, offsetPage*limit)
|
||||||
log.Printf(query)
|
log.Printf(query)
|
||||||
}else {
|
} else {
|
||||||
query = fmt.Sprintf("select * from users limit %d offset %d",limit,offsetPage*limit)
|
query = fmt.Sprintf("select * from users limit %d offset %d", limit, offsetPage*limit)
|
||||||
}
|
}
|
||||||
err := db.GetMysqlClient().Query2(query,&users)
|
err := db.GetMysqlClient().Query2(query, &users)
|
||||||
if nil != err{
|
if nil != err {
|
||||||
logs.Error(err.Error())
|
logs.Error(err.Error())
|
||||||
}
|
}
|
||||||
type Count struct {
|
type Count struct {
|
||||||
|
@ -38,11 +38,9 @@ func GetUsers(limit int32,offsetPage int32,name string) ([]Users,int32){
|
||||||
}
|
}
|
||||||
cnts := []Count{}
|
cnts := []Count{}
|
||||||
query = fmt.Sprintf("select count(*) as count from users")
|
query = fmt.Sprintf("select count(*) as count from users")
|
||||||
err = db.GetMysqlClient().Query2(query,&cnts)
|
err = db.GetMysqlClient().Query2(query, &cnts)
|
||||||
if nil != err{
|
if nil != err {
|
||||||
logs.Error(err.Error())
|
logs.Error(err.Error())
|
||||||
}
|
}
|
||||||
return users,cnts[0].Count
|
return users, cnts[0].Count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue