parent
8f83981e08
commit
6e30eb041d
@ -0,0 +1,6 @@
|
||||
/.idea/
|
||||
.idea/
|
||||
.idea
|
||||
/storage/logs/*
|
||||
/storage/uploaded/*
|
||||
/public/storage
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020 张奇峰
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
@ -0,0 +1,25 @@
|
||||
package destroy
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
"goskeleton/app/core/event_manage"
|
||||
"goskeleton/app/global/consts"
|
||||
"goskeleton/app/global/variable"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// 用于系统信号的监听
|
||||
go func() {
|
||||
c := make(chan os.Signal)
|
||||
signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGQUIT, syscall.SIGINT, syscall.SIGTERM) // 监听可能的退出信号
|
||||
received := <-c //接收信号管道中的值
|
||||
variable.ZapLog.Warn(consts.ProcessKilled, zap.String("信号值", received.String()))
|
||||
(event_manage.CreateEventManageFactory()).FuzzyCall(variable.EventDestroyPrefix)
|
||||
close(c)
|
||||
os.Exit(1)
|
||||
}()
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"goskeleton/app/global/consts"
|
||||
"goskeleton/app/global/variable"
|
||||
"goskeleton/app/service/upload_file"
|
||||
"goskeleton/app/utils/response"
|
||||
)
|
||||
|
||||
type Upload struct {
|
||||
}
|
||||
|
||||
// 文件上传是一个独立模块,给任何业务返回文件上传后的存储路径即可。
|
||||
// 开始上传
|
||||
func (u *Upload) StartUpload(context *gin.Context) {
|
||||
savePath := variable.BasePath + variable.ConfigYml.GetString("FileUploadSetting.UploadFileSavePath")
|
||||
if r, finnalSavePath := upload_file.Upload(context, savePath); r == true {
|
||||
response.Success(context, consts.CurdStatusOkMsg, finnalSavePath)
|
||||
} else {
|
||||
response.Fail(context, consts.FilesUploadFailCode, consts.FilesUploadFailMsg, "")
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package cors
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// 允许跨域
|
||||
func Next() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
method := c.Request.Method
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
c.Header("Access-Control-Allow-Headers", "Access-Control-Allow-Headers,Authorization,User-Agent, Keep-Alive, Content-Type, X-Requested-With,X-CSRF-Token,AccessToken,Token")
|
||||
c.Header("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT, PATCH, OPTIONS")
|
||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
|
||||
c.Header("Access-Control-Allow-Credentials", "true")
|
||||
|
||||
// 放行所有OPTIONS方法
|
||||
if method == "OPTIONS" {
|
||||
c.AbortWithStatus(http.StatusAccepted)
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package my_jwt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"goskeleton/app/global/my_errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 使用工厂创建一个 JWT 结构体
|
||||
func CreateMyJWT(signKey string) *JwtSign {
|
||||
if len(signKey) <= 0 {
|
||||
signKey = "goskeleton"
|
||||
}
|
||||
return &JwtSign{
|
||||
[]byte(signKey),
|
||||
}
|
||||
}
|
||||
|
||||
// 定义一个 JWT验签 结构体
|
||||
type JwtSign struct {
|
||||
SigningKey []byte
|
||||
}
|
||||
|
||||
// CreateToken 生成一个token
|
||||
func (j *JwtSign) CreateToken(claims CustomClaims) (string, error) {
|
||||
// 生成jwt格式的header、claims 部分
|
||||
tokenPartA := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
// 继续添加秘钥值,生成最后一部分
|
||||
return tokenPartA.SignedString(j.SigningKey)
|
||||
}
|
||||
|
||||
// 解析Token
|
||||
func (j *JwtSign) ParseToken(tokenString string) (*CustomClaims, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
return j.SigningKey, nil
|
||||
})
|
||||
if token == nil {
|
||||
return nil, errors.New(my_errors.ErrorsTokenInvalid)
|
||||
}
|
||||
if err != nil {
|
||||
if ve, ok := err.(*jwt.ValidationError); ok {
|
||||
if ve.Errors&jwt.ValidationErrorMalformed != 0 {
|
||||
return nil, errors.New(my_errors.ErrorsTokenMalFormed)
|
||||
} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
|
||||
return nil, errors.New(my_errors.ErrorsTokenNotActiveYet)
|
||||
} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
|
||||
// 如果 TokenExpired ,只是过期(格式都正确),我们认为他是有效的,接下可以允许刷新操作
|
||||
token.Valid = true
|
||||
goto labelHere
|
||||
} else {
|
||||
return nil, errors.New(my_errors.ErrorsTokenInvalid)
|
||||
}
|
||||
}
|
||||
}
|
||||
labelHere:
|
||||
if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
|
||||
return claims, nil
|
||||
} else {
|
||||
return nil, errors.New(my_errors.ErrorsTokenInvalid)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新token
|
||||
func (j *JwtSign) RefreshToken(tokenString string, extraAddSeconds int64) (string, error) {
|
||||
|
||||
if CustomClaims, err := j.ParseToken(tokenString); err == nil {
|
||||
CustomClaims.ExpiresAt = time.Now().Unix() + extraAddSeconds
|
||||
return j.CreateToken(*CustomClaims)
|
||||
} else {
|
||||
return "", err
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package data_type
|
||||
|
||||
type Page struct {
|
||||
Page float64 `form:"page" json:"page" binding:"min=1"` // 必填,页面值>=1
|
||||
Limit float64 `form:"limit" json:"limit" binding:"min=1"` // 必填,每页条数值>=1
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package register_validator
|
||||
|
||||
import (
|
||||
"goskeleton/app/core/container"
|
||||
"goskeleton/app/global/consts"
|
||||
"goskeleton/app/http/validator/api/home"
|
||||
)
|
||||
|
||||
// 各个业务模块验证器必须进行注册(初始化),程序启动时会自动加载到容器
|
||||
func ApiRegisterValidator() {
|
||||
//创建容器
|
||||
containers := container.CreateContainersFactory()
|
||||
|
||||
// key 按照前缀+模块+验证动作 格式,将各个模块验证注册在容器
|
||||
var key string
|
||||
|
||||
// 注册门户类表单参数验证器
|
||||
key = consts.ValidatorPrefix + "HomeNews"
|
||||
containers.Set(key, home.News{})
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package factory
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"goskeleton/app/core/container"
|
||||
"goskeleton/app/global/my_errors"
|
||||
"goskeleton/app/global/variable"
|
||||
"goskeleton/app/http/validator/core/interf"
|
||||
)
|
||||
|
||||
// 表单参数验证器工厂(请勿修改)
|
||||
func Create(key string) func(context *gin.Context) {
|
||||
|
||||
if value := container.CreateContainersFactory().Get(key); value != nil {
|
||||
if val, isOk := value.(interf.ValidatorInterface); isOk {
|
||||
return val.CheckParams
|
||||
}
|
||||
}
|
||||
variable.ZapLog.Error(my_errors.ErrorsValidatorNotExists + ", 验证器模块:" + key)
|
||||
return nil
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package interf
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
// 验证器接口,每个验证器必须实现该接口,请勿修改
|
||||
type ValidatorInterface interface {
|
||||
CheckParams(context *gin.Context)
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package users
|
||||
|
||||
type BaseField struct {
|
||||
UserName string `form:"user_name" json:"user_name" binding:"required,min=1"` // 必填、对于文本,表示它的长度>=1
|
||||
Pass string `form:"pass" json:"pass" binding:"required,min=6,max=20"` // 密码为 必填,长度>=6
|
||||
}
|
||||
|
||||
type Id struct {
|
||||
Id float64 `form:"id" json:"id" binding:"required,min=1"`
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package curd
|
||||
|
||||
import (
|
||||
"goskeleton/app/model"
|
||||
"goskeleton/app/utils/md5_encrypt"
|
||||
)
|
||||
|
||||
func CreateUserCurdFactory() *UsersCurd {
|
||||
return &UsersCurd{model.CreateUserFactory("")}
|
||||
}
|
||||
|
||||
type UsersCurd struct {
|
||||
userModel *model.UsersModel
|
||||
}
|
||||
|
||||
func (u *UsersCurd) Register(userName, pass, userIp string) bool {
|
||||
pass = md5_encrypt.Base64Md5(pass) // 预先处理密码加密,然后存储在数据库
|
||||
return u.userModel.Register(userName, pass, userIp)
|
||||
}
|
||||
|
||||
func (u *UsersCurd) Store(name string, pass string, realName string, phone string, remark string) bool {
|
||||
|
||||
pass = md5_encrypt.Base64Md5(pass) // 预先处理密码加密,然后存储在数据库
|
||||
return u.userModel.Store(name, pass, realName, phone, remark)
|
||||
}
|
||||
|
||||
func (u *UsersCurd) Update(id int, name string, pass string, realName string, phone string, remark string, clientIp string) bool {
|
||||
//预先处理密码加密等操作,然后进行更新
|
||||
pass = md5_encrypt.Base64Md5(pass) // 预先处理密码加密,然后存储在数据库
|
||||
return u.userModel.Update(id, name, pass, realName, phone, remark, clientIp)
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package on_open_success
|
||||
|
||||
// ClientMoreParams 为客户端成功上线后设置更多的参数
|
||||
// ws 客户端成功上线以后,可以通过客户端携带的唯一参数,在数据库查询更多的其他关键信息,设置在 *Client 结构体上
|
||||
// 这样便于在后续获取在线客户端时快速获取其他关键信息,例如:进行消息广播时记录日志可能需要更多字段信息等
|
||||
type ClientMoreParams struct {
|
||||
UserParams1 string `json:"user_params_1"` // 字段名称以及类型由 开发者自己定义
|
||||
UserParams2 string `json:"user_params_2"`
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package casbin_v2
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/model"
|
||||
gormadapter "github.com/casbin/gorm-adapter/v3"
|
||||
"gorm.io/gorm"
|
||||
"goskeleton/app/global/my_errors"
|
||||
"goskeleton/app/global/variable"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
//创建 casbin Enforcer(执行器)
|
||||
func InitCasbinEnforcer() (*casbin.SyncedEnforcer, error) {
|
||||
var tmpDbConn *gorm.DB
|
||||
var Enforcer *casbin.SyncedEnforcer
|
||||
switch strings.ToLower(variable.ConfigGormv2Yml.GetString("Gormv2.UseDbType")) {
|
||||
case "mysql":
|
||||
if variable.GormDbMysql == nil {
|
||||
return nil, errors.New(my_errors.ErrorCasbinCanNotUseDbPtr)
|
||||
}
|
||||
tmpDbConn = variable.GormDbMysql
|
||||
case "sqlserver", "mssql":
|
||||
if variable.GormDbSqlserver == nil {
|
||||
return nil, errors.New(my_errors.ErrorCasbinCanNotUseDbPtr)
|
||||
}
|
||||
tmpDbConn = variable.GormDbSqlserver
|
||||
case "postgre", "postgresql", "postgres":
|
||||
if variable.GormDbPostgreSql == nil {
|
||||
return nil, errors.New(my_errors.ErrorCasbinCanNotUseDbPtr)
|
||||
}
|
||||
tmpDbConn = variable.GormDbPostgreSql
|
||||
default:
|
||||
}
|
||||
|
||||
prefix := variable.ConfigYml.GetString("Casbin.TablePrefix")
|
||||
tbName := variable.ConfigYml.GetString("Casbin.TableName")
|
||||
|
||||
a, err := gormadapter.NewAdapterByDBUseTableName(tmpDbConn, prefix, tbName)
|
||||
if err != nil {
|
||||
return nil, errors.New(my_errors.ErrorCasbinCreateAdaptFail)
|
||||
}
|
||||
modelConfig := variable.ConfigYml.GetString("Casbin.ModelConfig")
|
||||
|
||||
if m, err := model.NewModelFromString(modelConfig); err != nil {
|
||||
return nil, errors.New(my_errors.ErrorCasbinNewModelFromStringFail + err.Error())
|
||||
} else {
|
||||
if Enforcer, err = casbin.NewSyncedEnforcer(m, a); err != nil {
|
||||
return nil, errors.New(my_errors.ErrorCasbinCreateEnforcerFail)
|
||||
}
|
||||
_ = Enforcer.LoadPolicy()
|
||||
AutoLoadSeconds := variable.ConfigYml.GetDuration("Casbin.AutoLoadPolicySeconds")
|
||||
Enforcer.StartAutoLoadPolicy(time.Second * AutoLoadSeconds)
|
||||
return Enforcer, nil
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package cur_userinfo
|
||||
|
||||
import (
|
||||
"github.com/gin-gonic/gin"
|
||||
"goskeleton/app/global/variable"
|
||||
"goskeleton/app/http/middleware/my_jwt"
|
||||
)
|
||||
|
||||
// GetCurrentUserId 获取当前用户的id
|
||||
// @context 请求上下文
|
||||
func GetCurrentUserId(context *gin.Context) (int64, bool) {
|
||||
tokenKey := variable.ConfigYml.GetString("Token.BindContextKeyName")
|
||||
currentUser, exist := context.MustGet(tokenKey).(my_jwt.CustomClaims)
|
||||
return currentUser.UserId, exist
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package gorm_v2
|
||||
|
||||
// 数据库参数配置,结构体
|
||||
// 用于解决复杂的业务场景连接到多台服务器部署的 mysql、sqlserver、postgresql 数据库
|
||||
// 具体用法参见常用开发模块:多源数据库的操作
|
||||
|
||||
type ConfigParams struct {
|
||||
Write ConfigParamsDetail
|
||||
Read ConfigParamsDetail
|
||||
}
|
||||
type ConfigParamsDetail struct {
|
||||
Host string
|
||||
DataBase string
|
||||
Port int
|
||||
Prefix string
|
||||
User string
|
||||
Pass string
|
||||
Charset string
|
||||
}
|
@ -0,0 +1,174 @@
|
||||
package gorm_v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go.uber.org/zap"
|
||||
gormLog "gorm.io/gorm/logger"
|
||||
"gorm.io/gorm/utils"
|
||||
"goskeleton/app/global/variable"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 自定义日志格式, 对 gorm 自带日志进行拦截重写
|
||||
func createCustomGormLog(sqlType string, options ...Options) gormLog.Interface {
|
||||
var (
|
||||
infoStr = "%s\n[info] "
|
||||
warnStr = "%s\n[warn] "
|
||||
errStr = "%s\n[error] "
|
||||
traceStr = "%s\n[%.3fms] [rows:%v] %s"
|
||||
traceWarnStr = "%s %s\n[%.3fms] [rows:%v] %s"
|
||||
traceErrStr = "%s %s\n[%.3fms] [rows:%v] %s"
|
||||
)
|
||||
logConf := gormLog.Config{
|
||||
SlowThreshold: time.Second * variable.ConfigGormv2Yml.GetDuration("Gormv2."+sqlType+".SlowThreshold"),
|
||||
LogLevel: gormLog.Warn,
|
||||
Colorful: false,
|
||||
}
|
||||
log := &logger{
|
||||
Writer: logOutPut{},
|
||||
Config: logConf,
|
||||
infoStr: infoStr,
|
||||
warnStr: warnStr,
|
||||
errStr: errStr,
|
||||
traceStr: traceStr,
|
||||
traceWarnStr: traceWarnStr,
|
||||
traceErrStr: traceErrStr,
|
||||
}
|
||||
for _, val := range options {
|
||||
val.apply(log)
|
||||
}
|
||||
return log
|
||||
}
|
||||
|
||||
type logOutPut struct{}
|
||||
|
||||
func (l logOutPut) Printf(strFormat string, args ...interface{}) {
|
||||
logRes := fmt.Sprintf(strFormat, args...)
|
||||
logFlag := "gorm_v2 日志:"
|
||||
detailFlag := "详情:"
|
||||
if strings.HasPrefix(strFormat, "[info]") || strings.HasPrefix(strFormat, "[traceStr]") {
|
||||
variable.ZapLog.Info(logFlag, zap.String(detailFlag, logRes))
|
||||
} else if strings.HasPrefix(strFormat, "[error]") || strings.HasPrefix(strFormat, "[traceErr]") {
|
||||
variable.ZapLog.Error(logFlag, zap.String(detailFlag, logRes))
|
||||
} else if strings.HasPrefix(strFormat, "[warn]") || strings.HasPrefix(strFormat, "[traceWarn]") {
|
||||
variable.ZapLog.Warn(logFlag, zap.String(detailFlag, logRes))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 尝试从外部重写内部相关的格式化变量
|
||||
type Options interface {
|
||||
apply(*logger)
|
||||
}
|
||||
type OptionFunc func(log *logger)
|
||||
|
||||
func (f OptionFunc) apply(log *logger) {
|
||||
f(log)
|
||||
}
|
||||
|
||||
// 定义 6 个函数修改内部变量
|
||||
func SetInfoStrFormat(format string) Options {
|
||||
return OptionFunc(func(log *logger) {
|
||||
log.infoStr = format
|
||||
})
|
||||
}
|
||||
|
||||
func SetWarnStrFormat(format string) Options {
|
||||
return OptionFunc(func(log *logger) {
|
||||
log.warnStr = format
|
||||
})
|
||||
}
|
||||
|
||||
func SetErrStrFormat(format string) Options {
|
||||
return OptionFunc(func(log *logger) {
|
||||
log.errStr = format
|
||||
})
|
||||
}
|
||||
|
||||
func SetTraceStrFormat(format string) Options {
|
||||
return OptionFunc(func(log *logger) {
|
||||
log.traceStr = format
|
||||
})
|
||||
}
|
||||
func SetTracWarnStrFormat(format string) Options {
|
||||
return OptionFunc(func(log *logger) {
|
||||
log.traceWarnStr = format
|
||||
})
|
||||
}
|
||||
|
||||
func SetTracErrStrFormat(format string) Options {
|
||||
return OptionFunc(func(log *logger) {
|
||||
log.traceErrStr = format
|
||||
})
|
||||
}
|
||||
|
||||
type logger struct {
|
||||
gormLog.Writer
|
||||
gormLog.Config
|
||||
infoStr, warnStr, errStr string
|
||||
traceStr, traceErrStr, traceWarnStr string
|
||||
}
|
||||
|
||||
// LogMode log mode
|
||||
func (l *logger) LogMode(level gormLog.LogLevel) gormLog.Interface {
|
||||
newlogger := *l
|
||||
newlogger.LogLevel = level
|
||||
return &newlogger
|
||||
}
|
||||
|
||||
// Info print info
|
||||
func (l logger) Info(_ context.Context, msg string, data ...interface{}) {
|
||||
if l.LogLevel >= gormLog.Info {
|
||||
l.Printf(l.infoStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Warn print warn messages
|
||||
func (l logger) Warn(_ context.Context, msg string, data ...interface{}) {
|
||||
if l.LogLevel >= gormLog.Warn {
|
||||
l.Printf(l.warnStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Error print error messages
|
||||
func (l logger) Error(_ context.Context, msg string, data ...interface{}) {
|
||||
if l.LogLevel >= gormLog.Error {
|
||||
l.Printf(l.errStr+msg, append([]interface{}{utils.FileWithLineNum()}, data...)...)
|
||||
}
|
||||
}
|
||||
|
||||
// Trace print sql message
|
||||
func (l logger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
|
||||
if l.LogLevel <= gormLog.Silent {
|
||||
return
|
||||
}
|
||||
|
||||
elapsed := time.Since(begin)
|
||||
switch {
|
||||
case err != nil && l.LogLevel >= gormLog.Error && (!errors.Is(err, gormLog.ErrRecordNotFound) || !l.IgnoreRecordNotFoundError):
|
||||
sql, rows := fc()
|
||||
if rows == -1 {
|
||||
l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, "-1", sql)
|
||||
} else {
|
||||
l.Printf(l.traceErrStr, utils.FileWithLineNum(), err, float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||
}
|
||||
case elapsed > l.SlowThreshold && l.SlowThreshold != 0 && l.LogLevel >= gormLog.Warn:
|
||||
sql, rows := fc()
|
||||
slowLog := fmt.Sprintf("SLOW SQL >= %v", l.SlowThreshold)
|
||||
if rows == -1 {
|
||||
l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, "-1", sql)
|
||||
} else {
|
||||
l.Printf(l.traceWarnStr, utils.FileWithLineNum(), slowLog, float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||
}
|
||||
case l.LogLevel == gormLog.Info:
|
||||
sql, rows := fc()
|
||||
if rows == -1 {
|
||||
l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, "-1", sql)
|
||||
} else {
|
||||
l.Printf(l.traceStr, utils.FileWithLineNum(), float64(elapsed.Nanoseconds())/1e6, rows, sql)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package error_record
|
||||
|
||||
import "goskeleton/app/global/variable"
|
||||
|
||||
// ErrorDeal 记录错误
|
||||
func ErrorDeal(err error) error {
|
||||
if err != nil {
|
||||
variable.ZapLog.Error(err.Error())
|
||||
}
|
||||
return err
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package publish_subscribe
|
||||
|
||||
import (
|
||||
amqp "github.com/rabbitmq/amqp091-go"
|
||||
"goskeleton/app/global/variable"
|
||||
)
|
||||
|
||||
// 等 go 泛型稳定以后,生产者和消费者初始化参数的设置,本段代码就可以继续精简
|
||||
// 目前 apply(*producer) 的参数只能固定为生产者或者消费者其中之一的具体类型
|
||||
|
||||
// 1.生产者初始化参数定义
|
||||
|
||||
// OptionsProd 定义动态设置参数接口
|
||||
type OptionsProd interface {
|
||||
apply(*producer)
|
||||
}
|
||||
|
||||
// OptionFunc 以函数形式实现上面的接口
|
||||
type OptionFunc func(*producer)
|
||||
|
||||
func (f OptionFunc) apply(prod *producer) {
|
||||
f(prod)
|
||||
}
|
||||
|
||||
// SetProdMsgDelayParams 开发者设置生产者初始化时的参数
|
||||
func SetProdMsgDelayParams(enableMsgDelayPlugin bool) OptionsProd {
|
||||
return OptionFunc(func(p *producer) {
|
||||
p.enableDelayMsgPlugin = enableMsgDelayPlugin
|
||||
p.exchangeType = "x-delayed-message"
|
||||
p.args = amqp.Table{
|
||||
"x-delayed-type": "fanout",
|
||||
}
|
||||
p.exchangeName = variable.ConfigYml.GetString("RabbitMq.PublishSubscribe.DelayedExchangeName")
|
||||
// 延迟消息队列,交换机、消息全部设置为持久
|
||||
p.durable = true
|
||||
})
|
||||
}
|
||||
|
||||
// 2.消费者端初始化参数定义
|
||||
|
||||
// OptionsConsumer 定义动态设置参数接口
|
||||
type OptionsConsumer interface {
|
||||
apply(*consumer)
|
||||
}
|
||||
|
||||
// OptionsConsumerFunc 以函数形式实现上面的接口
|
||||
type OptionsConsumerFunc func(*consumer)
|
||||
|
||||
func (f OptionsConsumerFunc) apply(cons *consumer) {
|
||||
f(cons)
|
||||
}
|
||||
|
||||
// SetConsMsgDelayParams 开发者设置消费者端初始化时的参数
|
||||
func SetConsMsgDelayParams(enableDelayMsgPlugin bool) OptionsConsumer {
|
||||
return OptionsConsumerFunc(func(c *consumer) {
|
||||
c.enableDelayMsgPlugin = enableDelayMsgPlugin
|
||||
c.exchangeType = "x-delayed-message"
|
||||
c.exchangeName = variable.ConfigYml.GetString("RabbitMq.PublishSubscribe.DelayedExchangeName")
|
||||
// 延迟消息队列,交换机、消息全部设置为持久
|
||||
c.durable = true
|
||||
})
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
amqp "github.com/rabbitmq/amqp091-go"
|
||||
"goskeleton/app/global/variable"
|
||||
)
|
||||
|
||||
// 等 go 泛型稳定以后,生产者和消费者初始化参数的设置,本段代码就可以继续精简
|
||||
// 目前 apply(*producer) 的参数只能固定为生产者或者消费者其中之一的具体类型
|
||||
|
||||
// 1.生产者初始化参数定义
|
||||
|
||||
// OptionsProd 定义动态设置参数接口
|
||||
type OptionsProd interface {
|
||||
apply(*producer)
|
||||
}
|
||||
|
||||
// OptionFunc 以函数形式实现上面的接口
|
||||
type OptionFunc func(*producer)
|
||||
|
||||
func (f OptionFunc) apply(prod *producer) {
|
||||
f(prod)
|
||||
}
|
||||
|
||||
// SetProdMsgDelayParams 开发者设置生产者初始化时的参数
|
||||
func SetProdMsgDelayParams(enableMsgDelayPlugin bool) OptionsProd {
|
||||
return OptionFunc(func(p *producer) {
|
||||
p.enableDelayMsgPlugin = enableMsgDelayPlugin
|
||||
p.exchangeType = "x-delayed-message"
|
||||
p.args = amqp.Table{
|
||||
"x-delayed-type": "direct",
|
||||
}
|
||||
p.exchangeName = variable.ConfigYml.GetString("RabbitMq.Routing.DelayedExchangeName")
|
||||
// 延迟消息队列,交换机、消息全部设置为持久
|
||||
p.durable = true
|
||||
})
|
||||
}
|
||||
|
||||
// 2.消费者端初始化参数定义
|
||||
|
||||
// OptionsConsumer 定义动态设置参数接口
|
||||
type OptionsConsumer interface {
|
||||
apply(*consumer)
|
||||
}
|
||||
|
||||
// OptionsConsumerFunc 以函数形式实现上面的接口
|
||||
type OptionsConsumerFunc func(*consumer)
|
||||
|
||||
func (f OptionsConsumerFunc) apply(cons *consumer) {
|
||||
f(cons)
|
||||
}
|
||||
|
||||
// SetConsMsgDelayParams 开发者设置消费者端初始化时的参数
|
||||
func SetConsMsgDelayParams(enableDelayMsgPlugin bool) OptionsConsumer {
|
||||
return OptionsConsumerFunc(func(c *consumer) {
|
||||
c.enableDelayMsgPlugin = enableDelayMsgPlugin
|
||||
c.exchangeType = "x-delayed-message"
|
||||
c.exchangeName = variable.ConfigYml.GetString("RabbitMq.Routing.DelayedExchangeName")
|
||||
// 延迟消息队列,交换机、消息全部设置为持久
|
||||
c.durable = true
|
||||
})
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package topics
|
||||
|
||||
import (
|
||||
amqp "github.com/rabbitmq/amqp091-go"
|
||||
"goskeleton/app/global/variable"
|
||||
)
|
||||
|
||||
// 等 go 泛型稳定以后,生产者和消费者初始化参数的设置,本段代码就可以继续精简
|
||||
// 目前 apply(*producer) 的参数只能固定为生产者或者消费者其中之一的具体类型
|
||||
|
||||
// 1.生产者初始化参数定义
|
||||
|
||||
// OptionsProd 定义动态设置参数接口
|
||||
type OptionsProd interface {
|
||||
apply(*producer)
|
||||
}
|
||||
|
||||
// OptionFunc 以函数形式实现上面的接口
|
||||
type OptionFunc func(*producer)
|
||||
|
||||
func (f OptionFunc) apply(prod *producer) {
|
||||
f(prod)
|
||||
}
|
||||
|
||||
// SetProdMsgDelayParams 开发者设置生产者初始化时的参数
|
||||
func SetProdMsgDelayParams(enableMsgDelayPlugin bool) OptionsProd {
|
||||
return OptionFunc(func(p *producer) {
|
||||
p.enableDelayMsgPlugin = enableMsgDelayPlugin
|
||||
p.exchangeType = "x-delayed-message"
|
||||
p.args = amqp.Table{
|
||||
"x-delayed-type": "topic",
|
||||
}
|
||||
p.exchangeName = variable.ConfigYml.GetString("RabbitMq.Topics.DelayedExchangeName")
|
||||
// 延迟消息队列,交换机、消息全部设置为持久
|
||||
p.durable = true
|
||||
})
|
||||
}
|
||||
|
||||
// 2.消费者端初始化参数定义
|
||||
|
||||
// OptionsConsumer 定义动态设置参数接口
|
||||
type OptionsConsumer interface {
|
||||
apply(*consumer)
|
||||
}
|
||||
|
||||
// OptionsConsumerFunc 以函数形式实现上面的接口
|
||||
type OptionsConsumerFunc func(*consumer)
|
||||
|
||||
func (f OptionsConsumerFunc) apply(cons *consumer) {
|
||||
f(cons)
|
||||
}
|
||||
|
||||
// SetConsMsgDelayParams 开发者设置消费者端初始化时的参数
|
||||
func SetConsMsgDelayParams(enableDelayMsgPlugin bool) OptionsConsumer {
|
||||
return OptionsConsumerFunc(func(c *consumer) {
|
||||
c.enableDelayMsgPlugin = enableDelayMsgPlugin
|
||||
c.exchangeType = "x-delayed-message"
|
||||
c.exchangeName = variable.ConfigYml.GetString("RabbitMq.Topics.DelayedExchangeName")
|
||||
// 延迟消息队列,交换机、消息全部设置为持久
|
||||
c.durable = true
|
||||
})
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package snow_flake
|
||||
|
||||
import (
|
||||
"goskeleton/app/global/consts"
|
||||
"goskeleton/app/global/variable"
|
||||
"goskeleton/app/utils/snow_flake/snowflake_interf"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 创建一个雪花算法生成器(生成工厂)
|
||||
func CreateSnowflakeFactory() snowflake_interf.InterfaceSnowFlake {
|
||||
return &snowflake{
|
||||
timestamp: 0,
|
||||
machineId: variable.ConfigYml.GetInt64("SnowFlake.SnowFlakeMachineId"),
|
||||
sequence: 0,
|
||||
}
|
||||
}
|
||||
|
||||
type snowflake struct {
|
||||
sync.Mutex
|
||||
timestamp int64
|
||||
machineId int64
|
||||
sequence int64
|
||||
}
|
||||
|
||||
// 生成分布式ID
|
||||
func (s *snowflake) GetId() int64 {
|
||||
s.Lock()
|
||||
defer func() {
|
||||
s.Unlock()
|
||||
}()
|
||||
now := time.Now().UnixNano() / 1e6
|
||||
if s.timestamp == now {
|
||||
s.sequence = (s.sequence + 1) & consts.SequenceMask
|
||||
if s.sequence == 0 {
|
||||
for now <= s.timestamp {
|
||||
now = time.Now().UnixNano() / 1e6
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s.sequence = 0
|
||||
}
|
||||
s.timestamp = now
|
||||
r := (now-consts.StartTimeStamp)<<consts.TimestampShift | (s.machineId << consts.MachineIdShift) | (s.sequence)
|
||||
return r
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package snowflake_interf
|
||||
|
||||
type InterfaceSnowFlake interface {
|
||||
GetId() int64
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package core
|
||||
|
||||
type Hub struct {
|
||||
//上线注册
|
||||
Register chan *Client
|
||||
//下线注销
|
||||
UnRegister chan *Client
|
||||
//所有在线客户端的内存地址
|
||||
Clients map[*Client]bool
|
||||
}
|
||||
|
||||
func CreateHubFactory() *Hub {
|
||||
return &Hub{
|
||||
Register: make(chan *Client),
|
||||
UnRegister: make(chan *Client),
|
||||
Clients: make(map[*Client]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *Hub) Run() {
|
||||
for {
|
||||
select {
|
||||
case client := <-h.Register:
|
||||
h.Clients[client] = true
|
||||
case client := <-h.UnRegister:
|
||||
if _, ok := h.Clients[client]; ok {
|
||||
_ = client.Conn.Close()
|
||||
delete(h.Clients, client)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package ymlconfig_interf
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type YmlConfigInterf interface {
|
||||
ConfigFileChangeListen()
|
||||
Clone(fileName string) YmlConfigInterf
|
||||
Get(keyName string) interface{}
|
||||
GetString(keyName string) string
|
||||
GetBool(keyName string) bool
|
||||
GetInt(keyName string) int
|
||||
GetInt32(keyName string) int32
|
||||
GetInt64(keyName string) int64
|
||||
GetFloat64(keyName string) float64
|
||||
GetDuration(keyName string) time.Duration
|
||||
GetStringSlice(keyName string) []string
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"goskeleton/app/global/variable"
|
||||
_ "goskeleton/bootstrap"
|
||||
"goskeleton/routers"
|
||||
)
|
||||
|
||||
// 这里可以存放门户类网站入口
|
||||
func main() {
|
||||
router := routers.InitApiRouter()
|
||||
_ = router.Run(variable.ConfigYml.GetString("HttpServer.Api.Port"))
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "goskeleton/bootstrap"
|
||||
cmd "goskeleton/command"
|
||||
)
|
||||
|
||||
// 开发非http接口类服务入口
|
||||
func main() {
|
||||
// 设置运行模式为 cli(console)
|
||||
cmd.Execute()
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"goskeleton/app/global/variable"
|
||||
_ "goskeleton/bootstrap"
|
||||
"goskeleton/routers"
|
||||
)
|
||||
|
||||
// 这里可以存放后端路由(例如后台管理系统)
|
||||
func main() {
|
||||
router := routers.InitWebRouter()
|
||||
_ = router.Run(variable.ConfigYml.GetString("HttpServer.Web.Port"))
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package demo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// 定义子命令
|
||||
var subCmd = &cobra.Command{
|
||||
Use: "subCmd",
|
||||
Short: "subCmd 命令简要介绍",
|
||||
Long: `命令使用详细介绍`,
|
||||
Args: cobra.ExactArgs(1), // 限制非flag参数的个数 = 1 ,超过1个会报错
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
fmt.Printf("%s\n", args[0])
|
||||
},
|
||||
}
|
||||
|
||||
//注册子命令
|
||||
func init() {
|
||||
Demo1.AddCommand(subCmd)
|
||||
// 子命令仍然可以定义 flag 参数,相关语法参见 demo.go 文件
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"goskeleton/command/demo"
|
||||
"goskeleton/command/demo_simple"
|
||||
"os"
|
||||
)
|
||||
|
||||
// cli 命令基于 https://github.com/spf13/cobra 封装
|
||||
// RootCmd represents the base command when called without any subcommands
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
Use: "Cli",
|
||||
Short: "A brief description of your application",
|
||||
Long: `A longer description that spans multiple lines and likely contains
|
||||
examples and usage of using your application. For example:
|
||||
|
||||
Cobra is a CLI library for Go that empowers applications.
|
||||
This application is a tool to generate the needed files
|
||||
to quickly create a Cobra application.`,
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the RootCmd.
|
||||
func Execute() {
|
||||
if err := RootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
// 如果子命令是存在于子目录,那么就需要在入口统一添加;
|
||||
// 如果和 root.go 同目录,则不需要像下一行一样添加
|
||||
RootCmd.AddCommand(demo.Demo1)
|
||||
RootCmd.AddCommand(demo_simple.DemoSimple)
|
||||
|
||||
}
|
@ -0,0 +1,297 @@
|
||||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
-- Dumped from database version 10.17
|
||||
-- Dumped by pg_dump version 10.17
|
||||
|
||||
-- Started on 2021-08-04 12:22:01
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
--
|
||||
-- TOC entry 5 (class 2615 OID 16570)
|
||||
-- Name: web; Type: SCHEMA; Schema: -; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE SCHEMA web;
|
||||
|
||||
|
||||
ALTER SCHEMA web OWNER TO postgres;
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_with_oids = false;
|
||||
|
||||
--
|
||||
-- TOC entry 200 (class 1259 OID 16609)
|
||||
-- Name: tb_auth_casbin_rule; Type: TABLE; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE TABLE web.tb_auth_casbin_rule (
|
||||
id integer NOT NULL,
|
||||
ptype character varying(100) DEFAULT 'p'::character varying NOT NULL,
|
||||
p0 character varying(100) DEFAULT ''::character varying NOT NULL,
|
||||
p1 character varying(100) DEFAULT ''::character varying NOT NULL,
|
||||
p2 character varying(100) DEFAULT ''::character varying NOT NULL,
|
||||
p3 character varying(100) DEFAULT ''::character varying NOT NULL,
|
||||
p4 character varying(100) DEFAULT ''::character varying NOT NULL,
|
||||
p5 character varying(100) DEFAULT ''::character varying NOT NULL,
|
||||
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
||||
v0 character varying(100),
|
||||
v1 character varying(100),
|
||||
v2 character varying(100),
|
||||
v3 character varying(100),
|
||||
v4 character varying(100),
|
||||
v5 character varying(100)
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE web.tb_auth_casbin_rule OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- TOC entry 199 (class 1259 OID 16607)
|
||||
-- Name: tb_auth_casbin_rule_id_seq; Type: SEQUENCE; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE SEQUENCE web.tb_auth_casbin_rule_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE web.tb_auth_casbin_rule_id_seq OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- TOC entry 2856 (class 0 OID 0)
|
||||
-- Dependencies: 199
|
||||
-- Name: tb_auth_casbin_rule_id_seq; Type: SEQUENCE OWNED BY; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER SEQUENCE web.tb_auth_casbin_rule_id_seq OWNED BY web.tb_auth_casbin_rule.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 202 (class 1259 OID 16629)
|
||||
-- Name: tb_oauth_access_tokens; Type: TABLE; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE TABLE web.tb_oauth_access_tokens (
|
||||
id integer NOT NULL,
|
||||
fr_user_id integer DEFAULT 0,
|
||||
client_id integer DEFAULT 1,
|
||||
token character varying(500) DEFAULT ''::character varying NOT NULL,
|
||||
action_name character varying(100) DEFAULT ''::character varying NOT NULL,
|
||||
scopes character varying(100) DEFAULT '*'::character varying NOT NULL,
|
||||
revoked smallint DEFAULT 0 NOT NULL,
|
||||
client_ip character varying(20) DEFAULT ''::character varying,
|
||||
expires_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE web.tb_oauth_access_tokens OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- TOC entry 201 (class 1259 OID 16627)
|
||||
-- Name: tb_oauth_access_tokens_id_seq; Type: SEQUENCE; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE SEQUENCE web.tb_oauth_access_tokens_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE web.tb_oauth_access_tokens_id_seq OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- TOC entry 2857 (class 0 OID 0)
|
||||
-- Dependencies: 201
|
||||
-- Name: tb_oauth_access_tokens_id_seq; Type: SEQUENCE OWNED BY; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER SEQUENCE web.tb_oauth_access_tokens_id_seq OWNED BY web.tb_oauth_access_tokens.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 198 (class 1259 OID 16591)
|
||||
-- Name: tb_users; Type: TABLE; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE TABLE web.tb_users (
|
||||
id integer NOT NULL,
|
||||
user_name character varying(30) DEFAULT ''::character varying NOT NULL,
|
||||
pass character varying(128) DEFAULT ''::character varying NOT NULL,
|
||||
real_name character varying(30) DEFAULT ''::character varying,
|
||||
phone character(11) DEFAULT ''::bpchar,
|
||||
status smallint DEFAULT 1,
|
||||
remark character varying(120) DEFAULT ''::character varying,
|
||||
last_login_time timestamp without time zone,
|
||||
last_login_ip character varying(20) DEFAULT ''::character varying,
|
||||
login_times integer DEFAULT 0,
|
||||
created_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at timestamp without time zone DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE web.tb_users OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- TOC entry 197 (class 1259 OID 16589)
|
||||
-- Name: tb_users_id_seq; Type: SEQUENCE; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE SEQUENCE web.tb_users_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE web.tb_users_id_seq OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- TOC entry 2858 (class 0 OID 0)
|
||||
-- Dependencies: 197
|
||||
-- Name: tb_users_id_seq; Type: SEQUENCE OWNED BY; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER SEQUENCE web.tb_users_id_seq OWNED BY web.tb_users.id;
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2696 (class 2604 OID 16612)
|
||||
-- Name: tb_auth_casbin_rule id; Type: DEFAULT; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY web.tb_auth_casbin_rule ALTER COLUMN id SET DEFAULT nextval('web.tb_auth_casbin_rule_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2708 (class 2604 OID 16632)
|
||||
-- Name: tb_oauth_access_tokens id; Type: DEFAULT; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY web.tb_oauth_access_tokens ALTER COLUMN id SET DEFAULT nextval('web.tb_oauth_access_tokens_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2685 (class 2604 OID 16594)
|
||||
-- Name: tb_users id; Type: DEFAULT; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY web.tb_users ALTER COLUMN id SET DEFAULT nextval('web.tb_users_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2848 (class 0 OID 16609)
|
||||
-- Dependencies: 200
|
||||
-- Data for Name: tb_auth_casbin_rule; Type: TABLE DATA; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2850 (class 0 OID 16629)
|
||||
-- Dependencies: 202
|
||||
-- Data for Name: tb_oauth_access_tokens; Type: TABLE DATA; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2846 (class 0 OID 16591)
|
||||
-- Dependencies: 198
|
||||
-- Data for Name: tb_users; Type: TABLE DATA; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2859 (class 0 OID 0)
|
||||
-- Dependencies: 199
|
||||
-- Name: tb_auth_casbin_rule_id_seq; Type: SEQUENCE SET; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
SELECT pg_catalog.setval('web.tb_auth_casbin_rule_id_seq', 1, false);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2860 (class 0 OID 0)
|
||||
-- Dependencies: 201
|
||||
-- Name: tb_oauth_access_tokens_id_seq; Type: SEQUENCE SET; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
SELECT pg_catalog.setval('web.tb_oauth_access_tokens_id_seq', 2, true);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2861 (class 0 OID 0)
|
||||
-- Dependencies: 197
|
||||
-- Name: tb_users_id_seq; Type: SEQUENCE SET; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
SELECT pg_catalog.setval('web.tb_users_id_seq', 8, true);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2721 (class 2606 OID 16626)
|
||||
-- Name: tb_auth_casbin_rule tb_auth_casbin_rule_pkey; Type: CONSTRAINT; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY web.tb_auth_casbin_rule
|
||||
ADD CONSTRAINT tb_auth_casbin_rule_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2723 (class 2606 OID 16647)
|
||||
-- Name: tb_oauth_access_tokens tb_oauth_access_tokens_pkey; Type: CONSTRAINT; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY web.tb_oauth_access_tokens
|
||||
ADD CONSTRAINT tb_oauth_access_tokens_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2718 (class 2606 OID 16606)
|
||||
-- Name: tb_users tb_users_pkey; Type: CONSTRAINT; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY web.tb_users
|
||||
ADD CONSTRAINT tb_users_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- TOC entry 2719 (class 1259 OID 16662)
|
||||
-- Name: idx_web_tb_auth_casbin_rule; Type: INDEX; Schema: web; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX idx_web_tb_auth_casbin_rule ON web.tb_auth_casbin_rule USING btree (ptype, v0, v1, v2, v3, v4, v5);
|
||||
|
||||
|
||||
-- Completed on 2021-08-04 12:22:02
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
@ -0,0 +1,52 @@
|
||||
-- 创建数据库,例如: db_goskeleton
|
||||
USE [master]
|
||||
IF NOT EXISTS(SELECT 1 FROM sysdatabases WHERE NAME=N'db_goskeleton')
|
||||
BEGIN
|
||||
CREATE DATABASE db_goskeleton
|
||||
END
|
||||
GO
|
||||
use db_goskeleton ;
|
||||
-- 创建用户表
|
||||
CREATE TABLE [dbo].[tb_users](
|
||||
[id] [int] IDENTITY(1,1) NOT NULL,
|
||||
[user_name] [nvarchar](50) NOT NULL ,
|
||||
[pass] [varchar](128) NOT NULL ,
|
||||
[real_name] [nvarchar](30) DEFAULT (''),
|
||||
[phone] [char](11) DEFAULT (''),
|
||||
[status] [tinyint] DEFAULT (1),
|
||||
[remark] [nvarchar](120) DEFAULT (''),
|
||||
[last_login_time] [datetime] DEFAULT (getdate()),
|
||||
[last_login_ip] [varchar](128) DEFAULT (''),
|
||||
[login_times] [int] DEFAULT ((0)),
|
||||
[created_at] [datetime] DEFAULT (getdate()),
|
||||
[updated_at] [datetime] DEFAULT (getdate())
|
||||
);
|
||||
-- -- 创建token表
|
||||
|
||||
CREATE TABLE [dbo].[tb_oauth_access_tokens](
|
||||
[id] [int] IDENTITY(1,1) NOT NULL,
|
||||
[fr_user_id] [int] DEFAULT ((0)),
|
||||
[client_id] [int] DEFAULT ((0)),
|
||||
[token] [varchar](500) DEFAULT (''),
|
||||
[action_name] [varchar](50) DEFAULT ('login') ,
|
||||
[scopes] [varchar](128) DEFAULT ('*') ,
|
||||
[revoked] [tinyint] DEFAULT ((0)),
|
||||
[client_ip] [varchar](128) DEFAULT (''),
|
||||
[created_at] [datetime] DEFAULT (getdate()) ,
|
||||
[updated_at] [datetime] DEFAULT (getdate()) ,
|
||||
[expires_at] [datetime] DEFAULT (getdate()) ,
|
||||
[remark] [nchar](120) DEFAULT ('')
|
||||
) ;
|
||||
|
||||
-- -- 创建 tb_casbin 接口鉴权表
|
||||
CREATE TABLE [dbo].[tb_auth_casbin_rule](
|
||||
[id] [int] IDENTITY(1,1) NOT NULL,
|
||||
[ptype] [varchar](100) DEFAULT ('p'),
|
||||
[v0] [varchar](100) DEFAULT (''),
|
||||
[v1] [varchar](100) DEFAULT (''),
|
||||
[v2] [varchar](100) DEFAULT (''),
|
||||
[v3] [varchar](100) DEFAULT (''),
|
||||
[v4] [varchar](100) DEFAULT (''),
|
||||
[v5] [varchar](100) DEFAULT (''),
|
||||
[remark] [nchar](120) DEFAULT ('')
|
||||
) ;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue