[ADD]first commit
This commit is contained in:
commit
e98c0f3b34
|
@ -0,0 +1,18 @@
|
|||
RUN_MODE = debug
|
||||
|
||||
[app]
|
||||
PAGE_SIZE = 10
|
||||
JWT_SECRET = 23347$040412
|
||||
|
||||
[server]
|
||||
HTTP_PORT = 8001
|
||||
READ_TIMEOUT = 60
|
||||
WRITE_TIMEOUT = 60
|
||||
|
||||
[database]
|
||||
TYPE = mysql
|
||||
USER = root
|
||||
PASSWORD = a19960425
|
||||
HOST = localhost:3306
|
||||
NAME = blog
|
||||
TABLE_PREFIX = blog_
|
|
@ -0,0 +1,40 @@
|
|||
module github.com/go-pripro/shop
|
||||
|
||||
go 1.15
|
||||
|
||||
require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/gin-gonic/gin v1.6.3
|
||||
github.com/go-ini/ini v1.61.0
|
||||
github.com/go-playground/validator/v10 v10.3.0 // indirect
|
||||
github.com/golang/protobuf v1.4.2 // indirect
|
||||
github.com/jinzhu/gorm v1.9.16
|
||||
github.com/json-iterator/go v1.1.10 // indirect
|
||||
github.com/lib/pq v1.2.0 // indirect
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect
|
||||
github.com/ugorji/go v1.1.8 // indirect
|
||||
github.com/unknwon/com v1.0.1
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect
|
||||
golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
gopkg.in/ini.v1 v1.61.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.3.0 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/go-pripro/shop/conf => ./shop/pkg/conf
|
||||
github.com/go-pripro/shop/docs => ./shop/docs
|
||||
github.com/go-pripro/shop/middleware => ./shop/middleware
|
||||
github.com/go-pripro/shop/models => ./shop/models
|
||||
github.com/go-pripro/shop/pkg/e => ./shop/pkg/e
|
||||
github.com/go-pripro/shop/pkg/logging => ./shop/pkg/logging
|
||||
github.com/go-pripro/shop/pkg/setting => ./shop/pkg/setting
|
||||
github.com/go-pripro/shop/pkg/util => ./shop/pkg/util
|
||||
github.com/go-pripro/shop/routers => ./shop/routers
|
||||
)
|
|
@ -0,0 +1,22 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-pripro/shop/pkg/setting"
|
||||
"github.com/go-pripro/shop/routers"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func main() {
|
||||
router := routers.InitRouter()
|
||||
|
||||
s := &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", setting.HTTPPort),
|
||||
Handler: router,
|
||||
ReadTimeout: setting.ReadTimeout,
|
||||
WriteTimeout: setting.WriteTimeout,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
|
||||
s.ListenAndServe()
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package jwt
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-pripro/shop/pkg/e"
|
||||
"github.com/go-pripro/shop/pkg/util"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func JWT() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
var code int
|
||||
var data interface{}
|
||||
code = e.SUCCESS
|
||||
token := c.Query("token")
|
||||
if token == "" {
|
||||
code = e.INVALID_PARAMS
|
||||
} else {
|
||||
claims, err := util.ParseToken(token)
|
||||
if err != nil {
|
||||
code = e.ERROR_AUTH_CHECK_TOKEN_FAIL
|
||||
} else if time.Now().Unix() > claims.ExpiresAt {
|
||||
code = e.ERROR_AUTH_CHECK_TOKEN_TIMEOUT
|
||||
}
|
||||
}
|
||||
if code != e.SUCCESS {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{
|
||||
"code" : code,
|
||||
"msg" : e.GetMsg(code),
|
||||
"data" : data,
|
||||
})
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-pripro/shop/pkg/setting"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"log"
|
||||
)
|
||||
|
||||
var db *gorm.DB
|
||||
|
||||
type Model struct {
|
||||
ID int `gorm:"primary_key" json:"id"`
|
||||
CreatedOn int `json:"created_on"`
|
||||
ModifiedOn int `json:"modified_on"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
var (
|
||||
err error
|
||||
dbType, dbName, user, password, host, tablePrefix string
|
||||
)
|
||||
|
||||
sec, err := setting.Cfg.GetSection("database")
|
||||
if err != nil {
|
||||
log.Fatal(2, "Fail to get section 'database': %v", err)
|
||||
}
|
||||
|
||||
dbType = sec.Key("TYPE").String()
|
||||
dbName = sec.Key("NAME").String()
|
||||
user = sec.Key("USER").String()
|
||||
password = sec.Key("PASSWORD").String()
|
||||
host = sec.Key("HOST").String()
|
||||
tablePrefix = sec.Key("TABLE_PREFIX").String()
|
||||
|
||||
db, err = gorm.Open(dbType, fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local",
|
||||
user,
|
||||
password,
|
||||
host,
|
||||
dbName))
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
|
||||
gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string {
|
||||
return tablePrefix + defaultTableName
|
||||
}
|
||||
|
||||
//db.AutoMigrate(&Tag{}, &Article{}, &Auth{})
|
||||
//db.SingularTable(true)
|
||||
db.LogMode(true)
|
||||
db.DB().SetMaxIdleConns(10)
|
||||
db.DB().SetMaxOpenConns(100)
|
||||
}
|
||||
|
||||
func CloseDB() {
|
||||
defer db.Close()
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package e
|
||||
|
||||
const (
|
||||
SUCCESS = 200
|
||||
ERROR = 500
|
||||
INVALID_PARAMS = 400
|
||||
|
||||
ERROR_EXIST_TAG = 10001
|
||||
ERROR_NOT_EXIST_TAG = 10002
|
||||
ERROR_NOT_EXIST_ARTICLE = 10003
|
||||
|
||||
ERROR_AUTH_CHECK_TOKEN_FAIL = 20001
|
||||
ERROR_AUTH_CHECK_TOKEN_TIMEOUT = 20002
|
||||
ERROR_AUTH_TOKEN = 20003
|
||||
ERROR_AUTH = 20004
|
||||
)
|
|
@ -0,0 +1,23 @@
|
|||
package e
|
||||
|
||||
var MsgFlags = map[int]string{
|
||||
SUCCESS: "ok",
|
||||
ERROR: "fail",
|
||||
INVALID_PARAMS: "请求参数错误",
|
||||
ERROR_EXIST_TAG: "已存在该标签名称",
|
||||
ERROR_NOT_EXIST_TAG: "该标签不存在",
|
||||
ERROR_NOT_EXIST_ARTICLE: "该文章不存在",
|
||||
ERROR_AUTH_CHECK_TOKEN_FAIL: "TOKEN鉴权失败",
|
||||
ERROR_AUTH_CHECK_TOKEN_TIMEOUT: "TOKEN已超时",
|
||||
ERROR_AUTH_TOKEN: "TOKEN生成失败",
|
||||
ERROR_AUTH: "TOKEN错误",
|
||||
}
|
||||
|
||||
func GetMsg(code int) string {
|
||||
msg, ok := MsgFlags[code]
|
||||
if ok {
|
||||
return msg
|
||||
}
|
||||
|
||||
return MsgFlags[ERROR]
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
LogSavePath = "runtime/logs/"
|
||||
LogSaveName = "log"
|
||||
LogFileExt = "log"
|
||||
TimeFormat = "20060102"
|
||||
)
|
||||
func getLogFilePath() string {
|
||||
return fmt.Sprintf("%s", LogSavePath)
|
||||
}
|
||||
func getLogFileFullPath() string {
|
||||
prefixPath := getLogFilePath()
|
||||
suffixPath := fmt.Sprintf("%s%s.%s", LogSaveName, time.Now().Format(TimeFormat), LogFileExt)
|
||||
return fmt.Sprintf("%s%s", prefixPath, suffixPath)
|
||||
}
|
||||
func openLogFile(filePath string) *os.File {
|
||||
_, err := os.Stat(filePath)
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
mkDir()
|
||||
case os.IsPermission(err):
|
||||
log.Fatalf("Permission :%v", err)
|
||||
}
|
||||
handle, err := os.OpenFile(filePath, os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("Fail to OpenFile :%v", err)
|
||||
}
|
||||
return handle
|
||||
}
|
||||
func mkDir() {
|
||||
dir, _ := os.Getwd()
|
||||
err := os.MkdirAll(dir + "/" + getLogFilePath(), os.ModePerm)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package logging
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
type Level int
|
||||
|
||||
var (
|
||||
F *os.File
|
||||
DefaultPrefix = ""
|
||||
DefaultCallerDepth = 2
|
||||
logger *log.Logger
|
||||
logPrefix = ""
|
||||
levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
|
||||
)
|
||||
|
||||
const (
|
||||
DEBUG Level = iota
|
||||
INFO
|
||||
WARNING
|
||||
ERROR
|
||||
FATAL
|
||||
)
|
||||
|
||||
func init() {
|
||||
filePath := getLogFileFullPath()
|
||||
F = openLogFile(filePath)
|
||||
logger = log.New(F, DefaultPrefix, log.LstdFlags)
|
||||
}
|
||||
func Debug(v ...interface{}) {
|
||||
setPrefix(DEBUG)
|
||||
logger.Println(v)
|
||||
}
|
||||
func Info(v ...interface{}) {
|
||||
setPrefix(INFO)
|
||||
logger.Println(v)
|
||||
}
|
||||
func Warn(v ...interface{}) {
|
||||
setPrefix(WARNING)
|
||||
logger.Println(v)
|
||||
}
|
||||
func Error(v ...interface{}) {
|
||||
setPrefix(ERROR)
|
||||
logger.Println(v)
|
||||
}
|
||||
func Fatal(v ...interface{}) {
|
||||
setPrefix(FATAL)
|
||||
logger.Fatalln(v)
|
||||
}
|
||||
func setPrefix(level Level) {
|
||||
_, file, line, ok := runtime.Caller(DefaultCallerDepth)
|
||||
if ok {
|
||||
logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line)
|
||||
} else {
|
||||
logPrefix = fmt.Sprintf("[%s]", levelFlags[level])
|
||||
}
|
||||
logger.SetPrefix(logPrefix)
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package setting
|
||||
|
||||
import (
|
||||
"github.com/go-ini/ini"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
var Cfg *ini.File
|
||||
var (
|
||||
RunMode string
|
||||
HTTPPort int
|
||||
ReadTimeout time.Duration
|
||||
WriteTimeout time.Duration
|
||||
PageSize int
|
||||
JwtSecret string
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
Cfg, err = ini.Load("conf/app.ini")
|
||||
if err != nil {
|
||||
log.Fatalf("Fail to parse 'conf/app.ini': %v", err)
|
||||
}
|
||||
|
||||
LoadBase()
|
||||
LoadServer()
|
||||
LoadApp()
|
||||
}
|
||||
|
||||
func LoadBase() {
|
||||
RunMode = Cfg.Section("").Key("RUN_MODE").MustString("debug")
|
||||
}
|
||||
|
||||
func LoadServer() {
|
||||
sec, err := Cfg.GetSection("server")
|
||||
if err != nil {
|
||||
log.Fatalf("Fail to get section 'sever' : %v", err)
|
||||
}
|
||||
|
||||
HTTPPort = sec.Key("HTTP_PORT").MustInt(8000)
|
||||
ReadTimeout = time.Duration(sec.Key("READ_TIMEOUT").MustUint(60)) * time.Second
|
||||
WriteTimeout = time.Duration(sec.Key("WRITE_TIMEOUT").MustInt(60)) * time.Second
|
||||
}
|
||||
|
||||
func LoadApp() {
|
||||
sec, err := Cfg.GetSection("app")
|
||||
if err != nil {
|
||||
log.Fatalf("Fail to get section 'app':%v", err)
|
||||
}
|
||||
|
||||
JwtSecret = sec.Key("JWT_SECRET").MustString("!@#!@#!@#!@@#!@#")
|
||||
PageSize = sec.Key("PAGE_SIZE").MustInt(10)
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
"github.com/go-pripro/shop/pkg/setting"
|
||||
"time"
|
||||
)
|
||||
|
||||
var jwtSecret = []byte(setting.JwtSecret)
|
||||
|
||||
type Claims struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
func GenerateToken(username, password string) (string, error) {
|
||||
nowTime := time.Now()
|
||||
expireTime := nowTime.Add(3 * time.Hour)
|
||||
|
||||
claims := Claims{
|
||||
username,
|
||||
password,
|
||||
jwt.StandardClaims{
|
||||
ExpiresAt: expireTime.Unix(),
|
||||
Issuer: "gin-blog",
|
||||
},
|
||||
}
|
||||
|
||||
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
token, err := tokenClaims.SignedString(jwtSecret)
|
||||
|
||||
return token, err
|
||||
}
|
||||
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
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-pripro/shop/pkg/setting"
|
||||
"github.com/unknwon/com"
|
||||
)
|
||||
|
||||
func GetPage(c *gin.Context) int {
|
||||
result := 0
|
||||
page, _ := com.StrTo(c.Query("page")).Int()
|
||||
if page > 0 {
|
||||
result = (page - 1) * setting.PageSize
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package routers
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-pripro/shop/pkg/setting"
|
||||
)
|
||||
|
||||
func InitRouter() *gin.Engine {
|
||||
r := gin.New()
|
||||
|
||||
r.Use(gin.Logger())
|
||||
|
||||
r.Use(gin.Recovery())
|
||||
|
||||
gin.SetMode(setting.RunMode)
|
||||
|
||||
r.GET("/ping", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "pong",
|
||||
})
|
||||
})
|
||||
r.GET("/test", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{
|
||||
"message": "test",
|
||||
})
|
||||
})
|
||||
|
||||
return r
|
||||
}
|
Loading…
Reference in New Issue