pipe

package module
v0.0.0-...-073189a Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2024 License: BSD-3-Clause Imports: 57 Imported by: 3

Documentation

Index

Constants

View Source
const (
	JwtPrefix      = "Bearer "
	JwtShortPrefix = "Short "
	JwtShortLen    = 12
)
View Source
const (
	// 默认代表所有域名的通配符
	RbacAllDomainDefault = "*"
	// 默认自身站点代号 可用于站点登录限制等
	RbacSelfDomainName = "self"
	// 登录
	RbacNotAllowLoginObj = "login"
	// 默认操作act
	RbacNormalAct = "POST"
)

Variables

View Source
var (
	// RequestCacheGet 请求缓存获取 必传params和db
	RequestCacheGet = &RunnerContext[any, *RequestCachePipe, rueidis.Client, *ParseResponse]{
		call: func(ctx iris.Context, origin any, params *RequestCachePipe, db rueidis.Client, more ...any) *RunResp[*ParseResponse] {
			if params == nil {
				params = new(RequestCachePipe)
			}
			cacheKey, err := params.GetCacheKey(ctx)
			if err != nil {
				return NewPipeErr[*ParseResponse](err)
			}

			resp := db.Do(ctx, db.B().Get().Key(cacheKey).Build())
			if resp.Error() != nil {
				if resp.Error() == rueidis.Nil {

					return NewPipeErr[*ParseResponse](nil)
				}
				return NewPipeErr[*ParseResponse](resp.Error())
			}
			raw, err := resp.ToString()
			if err != nil {
				return NewPipeErr[*ParseResponse](err)
			}
			var response *ParseResponse
			err = jsoniter.Unmarshal([]byte(raw), &response)
			if err != nil {
				return NewPipeErr[*ParseResponse](err)
			}

			return NewPipeResultErr[*ParseResponse](response, PipeCacheHasError).SetBreak(true)
		},
		Name: "请求缓存获取",
		Key:  "request_cache_get",
	}
	// RequestCacheSet 请求缓存设置
	RequestCacheSet = &RunnerContext[*ParseResponse, *RequestCachePipe, rueidis.Client, *ParseResponse]{
		call: func(ctx iris.Context, origin *ParseResponse, params *RequestCachePipe, db rueidis.Client, more ...any) *RunResp[*ParseResponse] {

			cacheKey, err := params.GetCacheKey(ctx)
			if err != nil {
				return NewPipeErr[*ParseResponse](err)
			}

			if _, ok := db.(rueidis.Client); !ok {
				return NewPipeErr[*ParseResponse](errors.New("获取rdb失败"))
			}
			rdb := db.(rueidis.Client)

			mpByte, _ := jsoniter.Marshal(origin)
			rdbResp := rdb.Do(ctx, rdb.B().Set().Key(cacheKey).Value(string(mpByte)).ExSeconds(int64(params.GetCacheTime().Seconds())).Build())
			if rdbResp.Error() != nil {
				return NewPipeErr[*ParseResponse](rdbResp.Error())
			}
			return NewPipeResult[*ParseResponse](nil)
		},
		Name: "请求缓存设置",
		Key:  "request_cache_set",
	}
)
View Source
var (
	// LocalCacheGet 本地缓存获取 使用 gcache
	// 必传params
	// 必传db 为gcache实例
	LocalCacheGet = &RunnerContext[any, *LocalCachePipe, gcache.Cache, any]{
		Name: "本地缓存获取",
		Key:  "local_cache_get",
		call: func(ctx iris.Context, origin any, params *LocalCachePipe, db gcache.Cache, more ...any) *RunResp[any] {

			if params == nil {
				return NewPipeErr[any](PipePackParamsError)
			}
			gc := db

			k, err := params.KeyGen.Build()
			if err != nil {
				return NewPipeErr[any](err)
			}
			v, err := gc.Get(k)
			if err != nil {
				if err != gcache.KeyNotFoundError {
					return NewPipeErr[any](err)
				}
				if params.EmptyRaise {
					return NewPipeErr[any](err)
				}
			} else {
				if !params.DisWriteHeader {
					ctx.Header("X-Cache", "1")
				}
			}

			return NewPipeResult(v)
		},
	}

	// LocalCacheSet 本地缓存设置 使用gcache
	// 必传params
	// 必传db 为gcache实例
	LocalCacheSet = &RunnerContext[any, *LocalCachePipe, gcache.Cache, any]{
		Name: "本地缓存设置",
		Key:  "local_cache_set",
		call: func(ctx iris.Context, origin any, params *LocalCachePipe, db gcache.Cache, more ...any) *RunResp[any] {
			if params == nil {
				return NewPipeErr[any](PipePackParamsError)
			}

			k, err := params.KeyGen.Build()
			if err != nil {
				return NewPipeErr[any](err)
			}

			err = db.SetWithExpire(k, params.Values, params.GetExpire())
			if err != nil {
				return NewPipeErr[any](err)
			}
			return NewPipeResult[any](params.Values)
		},
	}
)
View Source
var (
	// RbacGetRoles 获取rbac的规则
	// 必传params RbacGetRolePipe
	// 必传db 为RbacDomain的实例
	RbacGetRoles = &RunnerContext[any, *RbacGetRolePipe, *RbacDomain, []string]{
		Key:  "rbac_get_role",
		Name: "rbac权限获取",
		call: func(ctx iris.Context, origin any, params *RbacGetRolePipe, db *RbacDomain, more ...any) *RunResp[[]string] {
			roles, err := db.E.GetRolesForUser(params.UserId, params.Domain)
			if err != nil {
				return NewPipeErr[[]string](err)
			}
			return NewPipeResult(roles)
		},
	}
	// RbacAllow 判断rbac是否运行执行操作
	// 必传params RbacAllowPipe
	// 必传db 为RbacDomain的实例
	RbacAllow = &RunnerContext[any, *RbacAllowPipe, *RbacDomain, bool]{
		Key:  "rbac_allow",
		Name: "rbac权限允许执行",
		call: func(ctx iris.Context, origin any, params *RbacAllowPipe, db *RbacDomain, more ...any) *RunResp[bool] {
			if len(params.Sub) < 1 {
				return NewPipeErr[bool](errors.New("权限判断操作者不能为空"))
			}

			if len(params.Obj) < 1 {
				params.Obj = ctx.Path()
			}

			if len(params.Domain) < 1 {
				params.Domain = RbacSelfDomainName
			}

			if len(params.Act) < 1 {
				params.Act = ctx.Method()
			}

			pass := db.E.HasPolicy(params.Sub, params.Domain, params.Obj, params.Act)
			return NewPipeResult(pass)
		},
	}
)
View Source
var (
	// RedisCommand  redis单条操作
	// 必传params RedisOperate
	// 必传db
	RedisCommand = &RunnerContext[any, *RedisOperate, rueidis.Client, any]{
		Name: "redis单条操作",
		Key:  "redis_command",
		call: func(ctx iris.Context, origin any, params *RedisOperate, db rueidis.Client, more ...any) *RunResp[any] {

			if params == nil {
				return NewPipeErr[any](PipePackParamsError)
			}
			ab, err := params.Build()
			if err != nil {
				return NewPipeErr[any](err)
			}
			rdb := db

			redisCmd := rdb.B().Arbitrary(ab.Command)
			for _, kv := range ab.Keys {
				redisCmd.Keys(kv[0])
				if len(kv) >= 2 {
					redisCmd.Args(kv[1])
				}
			}
			redisCmd.Args(ab.Args...)
			resp := rdb.Do(ctx, redisCmd.Build())
			if resp.Error() != nil {
				if resp.Error() == rueidis.Nil {
					if !params.AllowNil {
						return NewPipeErr[any](resp.Error())
					}
					return NewPipeErr[any](nil)
				}
				return NewPipeErr[any](resp.Error())
			}

			result, err := params.RespParse(resp)
			return NewPipeResultErr(result, err)
		},
	}

	// RedisCommands  redis多条操作
	// 必传params RedisOperates
	// 必传db
	RedisCommands = &RunnerContext[any, *RedisOperates, rueidis.Client, []any]{
		Name: "多条redis操作",
		Key:  "redis_commands",
		call: func(ctx iris.Context, origin any, params *RedisOperates, db rueidis.Client, more ...any) *RunResp[[]any] {
			rdb := db
			cmdList := make(rueidis.Commands, 0, len(params.Records))
			for _, rc := range params.Records {
				ab, err := rc.Build()
				if err != nil {
					return NewPipeErr[[]any](err)
				}
				redisCmd := rdb.B().Arbitrary(ab.Command)
				for _, kv := range ab.Keys {
					redisCmd.Keys(kv[0])
					if len(kv) >= 2 {
						redisCmd.Args(kv[1])
					}
				}
				redisCmd.Args(ab.Args...)
				cmdList = append(cmdList, redisCmd.Build())
			}

			if len(cmdList) < 1 {
				return NewPipeErr[[]any](errors.New("redis命令组为空"))

			}

			var result = make([]any, 0, len(cmdList))

			for index, resp := range rdb.DoMulti(ctx, cmdList...) {
				if resp.Error() != nil {
					if resp.Error() == rueidis.Nil {
						if !params.Records[index].AllowNil {
							return NewPipeErr[[]any](resp.Error())
						}
						result = append(result, nil)
						continue
					}
					return NewPipeErr[[]any](resp.Error())
				}

				r, err := params.Records[index].RespParse(resp)
				if err != nil {
					return NewPipeErr[[]any](err)
				}
				result = append(result, r)
			}

			return NewPipeResult(result)
		},
	}
)
View Source
var (
	// SmsSend 短信发送
	// 必传params SmsPipe
	// 必传db SmsClient 的实例
	SmsSend = &RunnerContext[any, *SmsPipe, *SmsClient, string]{
		Name: "短信验证码发送",
		Key:  "sms_send",
		call: func(ctx iris.Context, origin any, params *SmsPipe, db *SmsClient, more ...any) *RunResp[string] {
			code, err := db.SendBeforeCheck(ctx, params.TemplateId, params.Mobile)
			return NewPipeResultErr(code, err)
		},
	}
	// SmsValid 短信验证码验证
	// 必传params SmsPipe
	// 必传db SmsClient 的实例
	SmsValid = &RunnerContext[any, *SmsPipe, *SmsClient, bool]{
		Name: "短信验证码验证",
		Key:  "sms_valid",
		call: func(ctx iris.Context, origin any, params *SmsPipe, db *SmsClient, more ...any) *RunResp[bool] {

			pass := db.Valid(ctx, params.Mobile, params.Code)
			if !pass {
				return NewPipeErr[bool](errors.New("短信验证码验证失败"))

			}
			db.DelKey(context.TODO(), params.Mobile)

			return NewPipeResult(pass)
		},
	}
)
View Source
var (
	// SwipeValidGet 滑块验证码获取
	// 必传db SwipeValidCode 的实例
	SwipeValidGet = &RunnerContext[any, any, *SwipeValidCode, string]{
		Name: "滑块验证码获取",
		Key:  "swipe_valid_get",
		call: func(ctx iris.Context, origin any, params any, db *SwipeValidCode, more ...any) *RunResp[string] {

			sp, err := db.Gen(ctx)
			if err != nil {
				return NewPipeErr[string](err)
			}
			raw := sp.ToString()
			sEnc := base64.StdEncoding.EncodeToString([]byte(raw))

			return NewPipeResult(sEnc)
		},
	}
	// SwipeValidCheck 滑块验证码验证
	// 必传db SwipeValidCode 的实例
	SwipeValidCheck = &RunnerContext[string, any, *SwipeValidCode, *SwipeValid]{
		Name: "滑块验证码验证",
		Key:  "swipe_valid_check",
		call: func(ctx iris.Context, origin string, params any, db *SwipeValidCode, more ...any) *RunResp[*SwipeValid] {
			check, err := db.Check(ctx, origin)
			if err != nil {
				return NewPipeErr[*SwipeValid](errors.New("验证失败 请重试"))
			}
			return NewPipeResult(check)
		},
	}
)
View Source
var (
	PipeSelectorParamsError  = errors.New("操作序列选择器参数错误")
	PipeDepNotFound          = errors.New("操作序列依赖项未找到")
	PipeSelectorNotFoundData = errors.New("操作序列获取内容为空")
	PipePackError            = errors.New("操作序列包参数错误")
	PipeDepError             = errors.New("操作序列依赖错误")
	PipeDbError              = errors.New("操作序列db报错")
	PipeOriginError          = errors.New("操作序列原始数据获取失败")
	PipePackParamsError      = errors.New("操作序列包内容参数错误")
	PipeParamsError          = errors.New("操作序列参数错误")
	PipeBreakError           = errors.New("操作序列主动跳出错误")
	PipeCacheHasError        = errors.New("有缓存主动返回")
	PipeRunAfterError        = errors.New("操作序列包执行错误")
	PipeRunAfterEmptyError   = errors.New("操作序列包解析后为空错误")
	PipeRatedError           = errors.New("太快了 请慢一点~")
)
View Source
var (
	// HashGen hash生成 必传params Type可选b62 b58
	HashGen = &RunnerContext[any, *HashGenPipe, any, string]{
		Name: "hash生成",
		Key:  "hash_gen",
		call: func(ctx iris.Context, origin any, params *HashGenPipe, db any, more ...any) *RunResp[string] {
			if len(params.Cols) < 1 {
				return NewPipeErr[string](PipePackParamsError)
			}

			var result string

			switch params.Type {
			case "b62":
				result = ut.StrToB62(strings.Join(params.Cols, ""))
				break
			case "b58":
				result = ut.StrToB58(strings.Join(params.Cols, ""))
				break
			default:
				return NewPipeErr[string](errors.New("hash生成类型错误"))
			}
			return NewPipeResult[string](result)
		},
	}
)
View Source
var (
	// HttpRequest 发起http请求  必传 params
	HttpRequest = &RunnerContext[any, *HttpRequestConfig, any, *req.Response]{
		Name: "http请求",
		Key:  "http_request",
		call: func(ctx iris.Context, origin any, params *HttpRequestConfig, db any, more ...any) *RunResp[*req.Response] {
			if params == nil {
				return NewPipeErr[*req.Response](PipePackParamsError)
			}

			if len(params.Uri) < 1 {
				return NewPipeErr[*req.Response](PipeParamsError)
			}

			r := req.R()
			r.SetHeaders(params.Headers)

			if params.PathParams != nil {
				r.SetPathParams(params.PathParams)
			}

			if params.UrlParams != nil {
				r.SetQueryParamsAnyType(params.UrlParams)
			}

			if params.GetMethod() != http.MethodGet {
				if params.Body != nil {
					r.SetBody(params.Body)
				}
			}

			resp, err := r.Send(params.GetMethod(), params.Uri)
			if err != nil {
				return NewPipeErr[*req.Response](err)
			}
			if resp.StatusCode != params.GetMustCode() {
				return NewPipeErr[*req.Response](errors.New(fmt.Sprintf("请求需要 %d 响应码 但得到了 %d", params.GetMustCode(), resp.StatusCode)))
			}
			if resp.IsErrorState() {
				return NewPipeErr[*req.Response](resp.Err)
			}

			return NewPipeResult[*req.Response](resp)
		},
	}
)
View Source
var (
	// ImgSafe 图像安全校验 必传 origin 是一个图像url地址
	ImgSafe = &RunnerContext[string, any, any, bool]{
		Name: "图片安全校验",
		Key:  "img_safe",
		call: func(ctx iris.Context, origin string, params any, db any, more ...any) *RunResp[bool] {

			if len(origin) < 1 {
				return NewPipeResult[bool](false)
			}
			pass, err := contentSafe.C.AutoHitImg(origin)
			return NewPipeResultErr[bool](pass, err)
		},
	}
)
View Source
var (
	// JwtCheck jwt验证
	// 必传origin JwtCheckDep
	// 必传db 为redis Client
	JwtCheck = &RunnerContext[*JwtCheckDep, any, rueidis.Client, JwtFlatBase]{
		Name: "jwt验证",
		Key:  "jwt_check",
		call: func(ctx iris.Context, origin *JwtCheckDep, params any, db rueidis.Client, more ...any) *RunResp[JwtFlatBase] {
			if origin == nil {
				return NewPipeErr[JwtFlatBase](PipeDepError)
			}

			dep := origin
			rdb := db
			helper := NewJwtHelper(rdb)

			pack := dep.FlatMap

			if len(pack.UserId) < 1 {
				return NewPipeErr[JwtFlatBase](errors.New("jwt数据包关键参数缺失"))
			}
			if len(pack.Env) < 1 {
				return NewPipeErr[JwtFlatBase](errors.New("jwt数据包参数缺失"))
			}
			if len(pack.Raw) < 1 {
				return NewPipeErr[JwtFlatBase](errors.New("jwt数据包结构错误"))
			}

			raw := pack.Raw

			if pack.IsShort() {

				resp := rdb.Do(ctx, rdb.B().Get().Key(helper.JwtRedisGenKey(pack.UserId, dep.Env)).Build())
				if resp.Error() != nil {

					if resp.Error() != rueidis.Nil {
						return NewPipeErr[JwtFlatBase](resp.Error())
					}

					return NewPipeErr[JwtFlatBase](errors.New("jwt数据获取失败"))

				}
				st, err := resp.ToString()
				if err != nil {
					return NewPipeErr[JwtFlatBase](err)
				}
				raw = strings.TrimPrefix(raw, JwtPrefix)
				if raw != st {
					return NewPipeErr[JwtFlatBase](errors.New("jwt数据包已过期"))
				}
				return NewPipeResult(pack)
			}

			if dep.Env != pack.Env {
				return NewPipeErr[JwtFlatBase](errors.New("jwt数据包环境校验失败"))
			}
			return NewPipeResult[JwtFlatBase](pack)
		},
	}
)
View Source
var (
	// JwtExchange jwt交换
	// 必传origin JwtCheckDep jwt解析出来的内容包
	// 必传params JwtGenPipe jwt的配置信息
	// 必传db redis Client
	JwtExchange = &RunnerContext[*JwtCheckDep, *JwtGenPipe, rueidis.Client, string]{
		Name: "jwt交换",
		Key:  "jwt_exchange",
		call: func(ctx iris.Context, origin *JwtCheckDep, params *JwtGenPipe, db rueidis.Client, more ...any) *RunResp[string] {
			if params == nil {
				params = new(JwtGenPipe)
			}

			resp := JwtVisit.call(ctx, origin, nil, db)
			if resp.Err != nil {
				return NewPipeErr[string](resp.Err)
			}
			flatMap := resp.Result

			if flatMap.IsShort() {
				return NewPipeErr[string](errors.New("短令牌无法生成短令牌"))
			}

			helper := NewJwtHelper(db)

			raw := flatMap.Raw
			raw = strings.TrimPrefix(raw, JwtPrefix)

			shortToken := ut.RandomStr(JwtShortLen)

			shortRedisKey := helper.JwtShortRedisGenKey(shortToken)
			err := helper.JwtSaveToken(ctx, shortRedisKey, raw, params.GetExpire(time.Hour))
			if err != nil {
				return NewPipeErr[string](err)
			}

			return NewPipeResult[string](shortToken)
		},
	}
)
View Source
var (
	// JwtFlat jwt解构出内容包
	// 必传origin 为Authorization头的字符串内容
	// 必传db 为redis Client
	JwtFlat = &RunnerContext[string, any, rueidis.Client, JwtFlatBase]{
		Name: "jwt解构",
		Key:  "jwt_flat",
		call: func(ctx iris.Context, origin string, params any, rdb rueidis.Client, more ...any) *RunResp[JwtFlatBase] {

			if len(origin) < 1 {
				return NewPipeErr[JwtFlatBase](errors.New("获取token令牌错误"))
			}

			helper := NewJwtHelper(rdb)
			isShort := strings.HasPrefix(origin, JwtShortPrefix)

			auth := origin

			if isShort {
				shortToken := strings.TrimPrefix(origin, JwtShortPrefix)
				if len(shortToken) != JwtShortLen {
					return NewPipeErr[JwtFlatBase](errors.New("短token令牌格式错误"))
				}

				resp := rdb.Do(ctx, rdb.B().Get().Key(helper.JwtShortRedisGenKey(shortToken)).Build())
				if resp.Error() != nil {
					return NewPipeErr[JwtFlatBase](resp.Error())
				}
				st, err := resp.ToString()
				if err != nil {
					return NewPipeErr[JwtFlatBase](err)
				}
				auth = JwtPrefix + st

			}

			if !strings.HasPrefix(auth, JwtPrefix) {
				return NewPipeErr[JwtFlatBase](errors.New("token令牌格式错误"))
			}

			tk, err := helper.TokenExtract(auth, ctJwt)
			if err != nil {
				return NewPipeErr[JwtFlatBase](err)
			}
			tk.Raw = auth

			return NewPipeResult(*tk)
		},
	}
)
View Source
var (
	// JwtGen jwt 结构设计 Strict模式下 用户一个env下仅可登陆一个设备  [key为userId:env]:value 为token
	// 必传origin jwt设置
	// 必传params 生成参数
	// 必传db redis Client
	JwtGen = &RunnerContext[*PipeJwtDep, *JwtGenPipe, rueidis.Client, string]{
		Name: "jwt生成",
		Key:  "jwt_gen",
		call: func(ctx iris.Context, origin *PipeJwtDep, params *JwtGenPipe, db rueidis.Client, more ...any) *RunResp[string] {
			if origin == nil {
				return NewPipeErr[string](PipeDepError)
			}

			if params == nil {
				params = new(JwtGenPipe)
			}

			helper := NewJwtHelper(db)

			redisKey := helper.JwtRedisGenKey(origin.UserId, origin.Env)

			if params.Strict {
				resp := helper.JwtRedisGetKey(ctx, redisKey)
				if resp.Error() != nil {

					if resp.Error() != rueidis.Nil {
						return NewPipeErr[string](resp.Error())
					}
				}

				st, _ := resp.ToString()
				if len(st) > 0 && !params.Force {
					return NewPipeErr[string](errors.New("当前环境有其他设备在线"))
				}
			}

			token := helper.GenJwtToken(origin.UserId, origin.Env)

			err := helper.JwtSaveToken(ctx, redisKey, token, params.GetExpire())
			if err != nil {
				return NewPipeErr[string](err)
			}

			return NewPipeResult[string](token)
		},
	}
)
View Source
var (
	// JwtVisit jwt一整套流程整合 对jwt自动续期
	// 必传origin JwtCheckDep jwt请求头包 需要有 Authorization 字段
	// 必传db 为redis Client
	JwtVisit = &RunnerContext[*JwtCheckDep, any, rueidis.Client, JwtFlatBase]{
		Name: "jwt显示",
		Key:  "jwt_visit",
		call: func(ctx iris.Context, origin *JwtCheckDep, params any, db rueidis.Client, more ...any) *RunResp[JwtFlatBase] {

			dep := origin
			resp := JwtFlat.call(ctx, dep.Authorization, nil, db)
			if resp.Err != nil {
				return NewPipeErr[JwtFlatBase](errors.Wrap(resp.Err, "解析结构"))
			}
			dep.FlatMap = resp.Result

			resp2 := JwtCheck.call(ctx, dep, nil, db)
			if resp2.Err != nil {
				return NewPipeErr[JwtFlatBase](errors.Wrap(resp2.Err, "验证安全"))
			}

			pack := resp.Result

			isShort := pack.IsShort()

			rdb := db
			helper := NewJwtHelper(rdb)

			if isShort {

				shortToken := strings.TrimPrefix(pack.Raw, JwtShortPrefix)
				shortRedisKey := helper.JwtShortRedisGenKey(shortToken)
				expireSec := int64(time.Hour.Seconds())

				err := rdb.Do(context.Background(), rdb.B().Expire().Key(shortRedisKey).Seconds(expireSec).Gt().Build()).Error()
				if err != nil {
					logger.J.ErrorE(err, "续期short token失败 %s ", shortToken)
				}
			} else {

				redisKey := helper.JwtRedisGenKey(pack.UserId, pack.Env)

				expireSec := int64(new(JwtGenPipe).GetExpire().Seconds())
				cmdList := rdb.B().Expire().Key(redisKey).Seconds(expireSec).Gt().Build()
				err := rdb.Do(context.Background(), cmdList).Error()
				if err != nil {
					logger.J.ErrorE(err, "续期token失败 %s %s", pack.UserId, pack.Env)
				}
			}
			return NewPipeResult(resp.Result)
		},
	}
)
View Source
var (
	// KvValid kv结构验证器 必传params
	KvValid = &RunnerContext[any, *KvValidConfig, any, bool]{
		Name: "kv验证器",
		Key:  "kv_valid",
		call: func(ctx iris.Context, origin any, params *KvValidConfig, db any, more ...any) *RunResp[bool] {
			if params == nil {
				return NewPipeErr[bool](PipePackParamsError)
			}

			pass, err := params.Check()
			if err != nil {
				return NewPipeErr[bool](err)
			}

			return NewPipeResult(pass)
		},
	}
)
View Source
var (
	// ModelAdd 模型json新增
	// 必传origin 支持map和struct 为模型的struct 对于传入struct会转换为map 通过json标签为key
	// 必传params ModelCtxAddConfig 配置信息 模型ID必须存在
	// 必传db 为qmgo的Database的实例
	ModelAdd = &RunnerContext[any, *ModelCtxAddConfig, *qmgo.Database, map[string]any]{
		Key:  "model_ctx_add",
		Name: "模型json新增",
		call: func(ctx iris.Context, origin any, params *ModelCtxAddConfig, db *qmgo.Database, more ...any) *RunResp[map[string]any] {
			if origin == nil {
				return NewPipeErr[map[string]any](PipeDepNotFound)
			}

			rawData := make(map[string]any)

			typ := reflect.TypeOf(origin)
			if typ.Kind() == reflect.Pointer {
				typ = typ.Elem()
			}

			switch typ.Kind() {
			case reflect.Struct:
				mp, err := ut.StructToMap(origin)
				if err != nil {
					return NewPipeErr[map[string]any](err)
				}
				rawData = mp
			case reflect.Map:
				rawData = origin.(map[string]any)
			default:
				return NewPipeErr[map[string]any](errors.New("origin 类型错误"))
			}

			mp := DefaultModelMap()
			mapper := &ut.ModelCtxMapperPack{
				InjectData: mp,
			}
			err := mapper.Process(rawData)
			if err != nil {
				return NewPipeErr[map[string]any](err)
			}

			_, err = db.Collection(params.ModelId).InsertOne(ctx, rawData)
			if err != nil {
				return NewPipeErr[map[string]any](err)
			}

			return NewPipeResult(rawData)
		},
	}
)
View Source
var (
	// ModelDel 模型单条删除
	// 必传params ModelDelConfig 必传modelId和rowId
	// 必传db 为qmgo的qmgo.Database
	ModelDel = &RunnerContext[any, *ModelDelConfig, *qmgo.Database, any]{
		Key:  "model_ctx_del",
		Name: "模型单条删除",
		call: func(ctx iris.Context, origin any, params *ModelDelConfig, db *qmgo.Database, more ...any) *RunResp[any] {
			ft := params.QueryFilter
			if ft == nil {
				ft = new(ut.QueryFull)
			}
			ft.And = append(ft.And, &ut.Kov{
				Key:   ut.DefaultUidTag,
				Value: params.RowId,
			})

			var result = make(map[string]any)
			pipeline := ut.QueryToMongoPipeline(ft)
			err := db.Collection(params.ModelId).Aggregate(ctx, pipeline).One(&result)
			if err != nil {
				return NewPipeErr[any](err)
			}

			err = db.Collection(params.ModelId).Remove(ctx, bson.M{ut.DefaultUidTag: params.RowId})
			if err != nil {
				return NewPipeErr[any](err)
			}
			return NewPipeResult[any]("ok")
		},
	}
)
View Source
var (
	// ModelMapper 模型body中映射取出对应的map 不需要db
	// 必传origin 支持map和struct struct以json的tag为key进行匹配
	// 必传params ut.ModelCtxMapperPack new(ut.ModelCtxMapperPack)都可以 但是必传
	ModelMapper = &RunnerContext[any, *ut.ModelCtxMapperPack, any, any]{
		Key:  "model_ctx_mapper",
		Name: "模型body取map",
		call: func(ctx iris.Context, origin any, params *ut.ModelCtxMapperPack, db any, more ...any) *RunResp[any] {
			var bodyData = origin
			if origin == nil {
				return NewPipeErr[any](PipeOriginError)
			}
			err := params.Process(bodyData)
			if err != nil {
				return NewPipeErr[any](err)
			}

			return NewPipeResult(bodyData)

		},
	}
)
View Source
var (
	// ModelPut 模型修改 origin需要是一个map或struct 只会修改与原始条目的diff项
	// 必传origin 可选struct或map 可以是ctx.ReadBody的映射
	// 必传params ModelPutConfig 其中ModelId和RowId必传
	// 必传db 为qmgo的Database
	ModelPut = &RunnerContext[any, *ModelPutConfig, *qmgo.Database, map[string]any]{
		Key:  "model_ctx_put",
		Name: "模型单条修改",
		call: func(ctx iris.Context, origin any, params *ModelPutConfig, db *qmgo.Database, more ...any) *RunResp[map[string]any] {
			if params == nil {
				return NewPipeErr[map[string]any](PipeParamsError)
			}
			if params.BodyMap == nil {
				return NewPipeErr[map[string]any](PipeOriginError)
			}
			bodyData := params.BodyMap

			ft := params.QueryFilter
			if ft == nil {
				ft = new(ut.QueryFull)
			}

			if ft.QueryParse == nil {
				ft.QueryParse = new(ut.QueryParse)
			}

			if ft.QueryParse.And == nil {
				ft.QueryParse.And = make([]*ut.Kov, 0)
			}
			if ft.QueryParse.Or == nil {
				ft.QueryParse.Or = make([]*ut.Kov, 0)
			}
			ft.QueryParse.And = append(ft.QueryParse.And, &ut.Kov{
				Key:   ut.DefaultUidTag,
				Value: params.RowId,
			})

			pipeline := ut.QueryToMongoPipeline(ft)

			// 获取原始那一条
			var result = make(map[string]any)
			err := db.Collection(params.ModelId).Aggregate(ctx, pipeline).One(&result)
			if err != nil {
				return NewPipeErr[map[string]any](err)
			}

			if origin == nil {
				origin = bodyData
			}

			diff := CompareAndDiff(origin, bodyData, result, "json")

			params.DropKeys = append(params.DropKeys, "_id", ut.DefaultUidTag)

			for _, key := range params.DropKeys {
				if _, ok := diff[key]; ok {
					delete(diff, key)
				}
			}

			if len(diff) < 1 {
				return NewPipeErr[map[string]any](errors.New("未获取到更新项"))
			}
			if params.UpdateTime {
				_, ok := diff["update_at"]
				if params.UpdateForce || !ok {
					diff["update_at"] = time.Now()
				}
			}

			err = db.Collection(params.ModelId).UpdateOne(ctx, bson.M{ut.DefaultUidTag: params.RowId}, bson.M{"$set": diff})
			if err != nil {
				return NewPipeErr[map[string]any](err)
			}

			return NewPipeResult[map[string]any](diff)
		},
	}
)
View Source
var (
	PipeBulkEmptySuccessError = errors.New("批量新增无一成功错误")
)
View Source
var (
	// QueryGetData 通过模型解析出query获取内容
	// 必传origin ModelGetDataDep 中的modelId
	// 必传params ModelGetData 需要设定为是否为单条以及是否获取匹配条数
	// 必传db 为qmgo的Database
	QueryGetData = &RunnerContext[*ModelGetDataDep, *ModelGetData, *qmgo.Database, *ut.MongoFacetResult]{
		Key:  "query_get_data",
		Name: "query获取数据",
		call: func(ctx iris.Context, origin *ModelGetDataDep, params *ModelGetData, db *qmgo.Database, more ...any) *RunResp[*ut.MongoFacetResult] {
			if params.Single {
				origin.Query.Page = 1
				origin.Query.PageSize = 1
			}
			origin.Query.GetCount = params.GetQueryCount
			pipeline := ut.QueryToMongoPipeline(origin.Query)

			var err error
			var all = new(ut.MongoFacetResult)

			if params.Single {
				var result = make(map[string]any)
				err = db.Collection(origin.ModelId).Aggregate(ctx, pipeline).One(&result)
				all.Data = result
			} else {
				if params.GetQueryCount {
					type inlineResp struct {
						Meta struct {
							Count int64 `json:"count"`
						}
						Data []map[string]any `json:"data,omitempty"`
					}
					var batch = new(inlineResp)
					err = db.Collection(origin.ModelId).Aggregate(ctx, pipeline).One(&batch)
					all.Data = batch.Data
					all.Count = batch.Meta.Count

				} else {
					var batch = make([]map[string]any, 0)
					err = db.Collection(origin.ModelId).Aggregate(ctx, pipeline).All(&batch)
					all.Data = batch
				}
			}
			if err != nil {
				return NewPipeErr[*ut.MongoFacetResult](err)
			}
			return NewPipeResult(all)
		},
	}
)
View Source
var (
	// QueryParse 根据约定规则从query中解析出mongodb的查询信息
	// 必传params QueryParseConfig 所有的fields都是以json tag为准
	QueryParse = &RunnerContext[any, *QueryParseConfig, any, *ut.QueryFull]{
		Key:  "model_ctx_query",
		Name: "模型query映射",
		call: func(ctx iris.Context, origin any, params *QueryParseConfig, db any, more ...any) *RunResp[*ut.QueryFull] {
			qs := ut.NewPruneCtxQuery()

			if params == nil {
				params = new(QueryParseConfig)
			}

			var urlParams = params.UrlParams
			if urlParams == nil {
				urlParams = ctx.URLParams()
			}

			mapper, err := qs.PruneParse(urlParams, params.SearchFields, params.GeoKey)
			if err != nil {
				return NewPipeErr[*ut.QueryFull](err)
			}

			if params.InjectAnd != nil {
				mapper.QueryParse.InsertOrReplaces("and", params.InjectAnd...)
			}
			if params.InjectOr != nil {
				mapper.QueryParse.InsertOrReplaces("or", params.InjectOr...)
			}
			mapper.Pks = params.Pks
			return NewPipeResult(mapper)

		},
	}
)
View Source
var (
	// RandomGen 随机数生成
	// 必传params RandomPipe
	RandomGen = &RunnerContext[any, *RandomPipe, any, any]{
		Name: "随机数生成",
		Key:  "random",
		call: func(ctx iris.Context, origin any, params *RandomPipe, db any, more ...any) *RunResp[any] {

			var result any

			switch params.NeedType {
			case "string":
				if params.Len < 1 {
					return NewPipeErr[any](errors.New("需要指定生成的字符串位数"))
				}
				result = ut.RandomStr(int(params.Len))
				break
			case "int":
				if params.End < params.Start {
					return NewPipeErr[any](errors.New("截止值应该大于起始值"))

				}
				result = ut.RandomInt(int(params.End), int(params.Start))
				break
			default:
				return NewPipeErr[any](errors.New("生成器类型未被支持"))
			}

			return NewPipeResult(result)
		},
	}
)
View Source
var (
	// RequestRate 限速器 使用 https://github.com/ulule/limiter 实现
	// 必传params RateLimitPipe
	RequestRate = &RunnerContext[any, *RateLimitPipe, any, any]{
		Name: "请求限速",
		Key:  "request_rate",
		call: func(ctx iris.Context, origin any, params *RateLimitPipe, db any, more ...any) *RunResp[any] {

			if params == nil {
				return NewPipeErr[any](PipePackParamsError)
			}
			k, err := params.KeyGen.Build()
			if err != nil {
				return NewPipeErr[any](err)
			}

			client, err := params.genClient()
			if err != nil {
				return NewPipeErr[any](err)
			}

			rateCtx, err := client.Get(ctx, k)
			if err != nil {
				return NewPipeErr[any](err)
			}

			if params.WriteHeader {
				ctx.Header("X-RateLimit-Limit", strconv.FormatInt(rateCtx.Limit, 10))
				ctx.Header("X-RateLimit-Remaining", strconv.FormatInt(rateCtx.Remaining, 10))
				ctx.Header("X-RateLimit-Reset", strconv.FormatInt(rateCtx.Reset, 10))
			}

			if rateCtx.Reached {

				return NewPipeErr[any](PipeRatedError).SetReqCode(http.StatusTooManyRequests)
			}
			return NewPipeResult[any](nil)
		},
	}
)
View Source
var (
	// ResponseParse 请求返回值的设定与解析
	// 必传params ReqResponse
	ResponseParse = &RunnerContext[any, *ReqResponse, any, *ParseResponse]{
		Name: "返回值解析",
		Key:  "response_parse",
		call: func(ctx iris.Context, origin any, params *ReqResponse, db any, more ...any) *RunResp[*ParseResponse] {

			if params == nil {
				return NewPipeErr[*ParseResponse](PipePackParamsError)
			}

			var pr = new(ParseResponse)

			if params.Type == "string" && len(params.Msg) >= 1 {
				pr.Msg = params.Msg
			} else {
				pr.Json = nil

				if params.Items != nil {

					respMap := params.Items

					if len(params.Excludes) > 0 {
						for _, exclude := range params.Excludes {
							tls := strings.Split(exclude, ".")
							if len(tls) == 1 {
								delete(respMap, exclude)
								continue
							}

							if len(tls) == 2 {
								top := tls[0]
								if v, ok := respMap[top]; ok {
									if vt, ok := v.(map[string]any); ok {
										delete(vt, tls[1])
									}
								}
							}
						}
					}

					switch params.Type {
					case "string":
						st, err := jsoniter.MarshalToString(respMap)
						if err != nil {
							return NewPipeErr[*ParseResponse](errors.Wrap(err, "返回值转换为字符串失败"))
						}
						pr.Msg = st
						break
					default:
						pr.Json = respMap
						break
					}

				}

			}
			return NewPipeResult(pr)
		},
	}
)
View Source
var (
	// RulesValid 规则验证 使用github.com/gookit/validate库 基于语义可验证map
	// 必传params RulesValidate 格式是这样的 required|int|min:1|max:99
	RulesValid = &RunnerContext[any, *RulesValidate, any, ValidResult]{
		Name: "规则验证",
		Key:  "rules_valid",
		call: func(ctx iris.Context, origin any, params *RulesValidate, db any, more ...any) *RunResp[ValidResult] {
			if params == nil {
				return NewPipeErr[ValidResult](PipePackParamsError)
			}

			mp := make(map[string]any)
			for _, rv := range params.Record {
				tv, err := ut.TypeChange(rv.Value, rv.NeedType)
				if err != nil {
					return NewPipeErr[ValidResult](err)
				}
				mp[rv.Key] = tv
			}

			result := params.Valid(mp)
			if !result.Pass {
				return NewPipeErr[ValidResult](errors.New(result.Msg))
			}

			return NewPipeResult(result)

		},
	}
)
View Source
var (
	// SchemaValid 基于json schema的验证器
	// 必传origin 为待验证的数据 只能是map
	// 必传params SchemaValidConfig 必包含schema
	SchemaValid = &RunnerContext[map[string]any, *SchemaValidConfig, any, map[string]any]{
		Name: "schema验证器",
		Key:  "schema_valid",
		call: func(ctx iris.Context, origin map[string]any, params *SchemaValidConfig, db any, more ...any) *RunResp[map[string]any] {
			if origin == nil {
				return NewPipeErr[map[string]any](PipeDepError)
			}

			if params == nil {
				return NewPipeErr[map[string]any](PipePackParamsError)
			}

			rawBin, err := jsoniter.Marshal(params.Schema)
			if err != nil {
				return NewPipeErr[map[string]any](err)
			}

			err = SchemaValidFunc(rawBin, origin)
			if err != nil {
				return NewPipeErr[map[string]any](err)
			}

			return NewPipeResult(origin)
		},
	}
)
View Source
var (
	// TextSafe 文字安全校验
	// 必传origin 为待校验文字
	TextSafe = &RunnerContext[string, any, any, bool]{
		Name: "文字安全验证",
		Key:  "text_safe",
		call: func(ctx iris.Context, origin string, params any, db any, more ...any) *RunResp[bool] {

			value := origin
			if len(value) > 1 {
				result, msg := contentSafe.C.AutoHitText(value)
				if !result {
					return NewPipeResultErr(result, errors.New(fmt.Sprintf("文字安全校验失败 错误:%s", msg)))
				}
				return NewPipeResult(result)
			}

			return NewPipeResult(false)
		},
	}
)

Functions

func AcquireLock

func AcquireLock(rdb rueidiscompat.Cmdable, key string, value string, expiration time.Duration) bool

AcquireLock 加锁 需要设置key和value 以及锁的时间

func CbcRegisterHandler

func CbcRegisterHandler[T any](route string, handler Handler[T])

func CompareAndDiff

func CompareAndDiff(origin interface{}, bodyData map[string]interface{}, oldData map[string]interface{}, tagName string) map[string]interface{}

CompareAndDiff 对比不同 逻辑是出现在bodyData中的 然后origin与oldData不一致的 则返回一个diff Map

func CtxGetEnv

func CtxGetEnv(ctx iris.Context, defaultStr ...string) string

CtxGetEnv 从ua中读取出env环境变量

func DefaultModelMap

func DefaultModelMap() map[string]any

func FastMsgMap

func FastMsgMap(code int, msg string, pipeNames ...string) iris.Map

func GenUUid

func GenUUid() string

func GetLen

func GetLen(input any) (float64, error)

func GetModelAllCount

func GetModelAllCount(ctx context.Context, db *qmgo.Database, modelId string) (int64, error)

GetModelAllCount 使用 metadata 统计文档数量 https://www.mongodb.com/docs/drivers/go/current/fundamentals/crud/read-operations/count/

func MapToSliceAny

func MapToSliceAny(input map[string]any) ([]any, error)

func MapToSliceString

func MapToSliceString(input map[string]any) ([]string, error)

func MongoBulkInsert

func MongoBulkInsert[T any](ctx context.Context, db *qmgo.Collection, accounts ...T) error

func MongoBulkInsertCount

func MongoBulkInsertCount[T any](ctx context.Context, db *qmgo.Collection, accounts ...T) (int, error)

func MongoBulkInsertCountMustRetry

func MongoBulkInsertCountMustRetry[T any](ctx context.Context, db *qmgo.Collection, accounts ...T) (int, error)

func MongoBulkInsertCountRetry

func MongoBulkInsertCountRetry[T any](ctx context.Context, db *qmgo.Collection, retryCount uint, retryInterval time.Duration, accounts ...T) (int, error)

func MongoFilterGetOne

func MongoFilterGetOne[T any](ctx context.Context, db *qmgo.Collection, filters bson.M) (*T, error)

func MongoFilters

func MongoFilters[T any](ctx context.Context, db *qmgo.Collection, filters bson.M) ([]T, error)

func MongoGetOne

func MongoGetOne[T any](ctx context.Context, db *qmgo.Collection, uid string) (*T, error)

MongoGetOne 传入实例 返回new之后的指针

func MongoIterateByBatch

func MongoIterateByBatch[T IMongoBase](ctx context.Context, db *qmgo.Collection, filter bson.M, selects bson.M, batchSize int64, processFunc func([]T) error) error

func MongoRandom

func MongoRandom[T any](ctx context.Context, db *qmgo.Collection, filters bson.D, count int) ([]T, error)

func MongoUpdateOne

func MongoUpdateOne(ctx context.Context, db *qmgo.Collection, uid string, pack bson.M) error

func OpValid

func OpValid(input any, op string, value string) bool

OpValid 操作符验证

func ReleaseLock

func ReleaseLock(client rueidiscompat.Cmdable, key string, value string) error

ReleaseLock 释放锁 必须传入正确的key和value才能释放 使用lua脚本

func SchemaValidFunc

func SchemaValidFunc(schema []byte, input map[string]any) error

SchemaValidFunc 验证数据

func SfNextId

func SfNextId() string

func ToJsonSchema

func ToJsonSchema[T any](origin T, omitFields ...string) *jsonschema.Schema

func ToMap

func ToMap(v interface{}) (map[string]interface{}, error)

Types

type AccountCoin

type AccountCoin struct {
	Balance     uint64 `json:"balance,omitempty" bson:"balance,omitempty" comment:"余额(分)" `           // 余额 单位是分
	ReferrerUid string `json:"referrer_uid,omitempty" bson:"referrer_uid,omitempty" comment:"介绍人uid"` // 介绍人
}

func (*AccountCoin) GetBalance

func (a *AccountCoin) GetBalance() uint64

func (*AccountCoin) GetReferrerUid

func (a *AccountCoin) GetReferrerUid() string

func (*AccountCoin) SetBalance

func (a *AccountCoin) SetBalance(newBalance uint64)

func (*AccountCoin) SetReferrerUid

func (a *AccountCoin) SetReferrerUid(referrer string)

type AccountComm

type AccountComm struct {
	AvatarUrl string `json:"avatar_url,omitempty" bson:"avatar_url,omitempty" comment:"头像地址"` // 头像地址
	NickName  string `json:"nick_name,omitempty" bson:"nick_name,omitempty" comment:"昵称"`     // 昵称
	Disable   bool   `json:"disable,omitempty" bson:"disable" comment:"是否禁用"`
	Msg       string `json:"msg,omitempty" bson:"msg,omitempty" comment:"状态说明"`
}

func (*AccountComm) GetAvatarUrl

func (a *AccountComm) GetAvatarUrl() string

func (*AccountComm) GetDisable

func (a *AccountComm) GetDisable() bool

func (*AccountComm) GetMsg

func (a *AccountComm) GetMsg() string

func (*AccountComm) GetNickName

func (a *AccountComm) GetNickName() string

func (*AccountComm) SetAvatarUrl

func (a *AccountComm) SetAvatarUrl(uri string)

func (*AccountComm) SetDisable

func (a *AccountComm) SetDisable(newDisable bool)

func (*AccountComm) SetMsg

func (a *AccountComm) SetMsg(newMsg string)

func (*AccountComm) SetNickName

func (a *AccountComm) SetNickName(name string)

type AccountPass

type AccountPass struct {
	UserName string `json:"user_name,omitempty" bson:"user_name,omitempty" comment:"用户名"`
	Password string `json:"password,omitempty" bson:"password,omitempty" comment:"加密后登录密码"`
	Salt     string `json:"salt,omitempty" bson:"salt,omitempty" comment:"密码加密salt"`
	Email    string `json:"email,omitempty" bson:"email,omitempty" comment:"邮箱地址"`
	TelPhone string `json:"tel_phone,omitempty" bson:"tel_phone,omitempty" comment:"电话号码"` // 电话号码
}

func (*AccountPass) GetEmail

func (a *AccountPass) GetEmail() string

func (*AccountPass) GetPassword

func (a *AccountPass) GetPassword() string

func (*AccountPass) GetTelPhone

func (a *AccountPass) GetTelPhone() string

func (*AccountPass) GetUserName

func (a *AccountPass) GetUserName() string

func (*AccountPass) PasswordMd5

func (a *AccountPass) PasswordMd5(rawPassword string) (m5ps string, salt string)

PasswordMd5 通过原始密码生成加密的m5为password

func (*AccountPass) SetEmail

func (a *AccountPass) SetEmail(newEmail string)

func (*AccountPass) SetPassword

func (a *AccountPass) SetPassword(newPassword string)

SetPassword 设置密码 明文 会自动加密

func (*AccountPass) SetTelPhone

func (a *AccountPass) SetTelPhone(newTelPhone string)

func (*AccountPass) SetUserName

func (a *AccountPass) SetUserName(newUserName string)

func (*AccountPass) ValidPassword

func (a *AccountPass) ValidPassword(rawPassword string) bool

ValidPassword 验证密码输出是否正确 password 为输入密码

type AccountPlatform

type AccountPlatform struct {
	Appid      string                 `json:"appid,omitempty" bson:"appid,omitempty" comment:"平台appid"`    // 同样是微信小程序 可能有多个应用 这就是应用id
	Name       string                 `json:"name,omitempty" bson:"name,omitempty" comment:"平台名称"`         // 微信小程序 抖音
	Pid        string                 `json:"pid,omitempty" bson:"pid,omitempty" comment:"平台ID"`           // 常见于微信的openid
	UnionId    string                 `json:"union_id,omitempty" bson:"union_id,omitempty" comment:"通用ID"` // 常见于微信的unionid
	NickName   string                 `json:"nick_name,omitempty" bson:"nick_name,omitempty" comment:"平台昵称"`
	AvatarUrl  string                 `json:"avatar_url,omitempty" bson:"avatar_url,omitempty" comment:"平台头像"`
	Password   string                 `json:"password,omitempty" bson:"password,omitempty" comment:"密码"`
	Phone      string                 `json:"phone,omitempty" bson:"phone,omitempty" comment:"手机号"`                // 平台绑定的手机号码 与用户手机号码可能不同
	Scopes     []string               `json:"scopes,omitempty" bson:"scopes,omitempty" comment:"授权范围"`             // 平台的授权范围
	AuthorTime time.Time              `json:"author_time,omitempty" bson:"author_time,omitempty" comment:"平台授权时间"` // 如果是第三方授权 则有一个授权时间
	PublicData *AccountPlatformPublic `json:"public_data,omitempty" bson:"public_data,omitempty" comment:"平台公共数据"`
}

type AccountPlatformPublic

type AccountPlatformPublic struct {
	Favorite    int    `json:"favorite,omitempty" bson:"favorite,omitempty" comment:"我的收藏数量"` // 用于我的收藏数量
	Digg        int    `json:"digg,omitempty" bson:"digg,omitempty" comment:"被点赞数量"`          // 用于我的作品的被点赞数量
	WorkCount   int    `json:"work_count,omitempty" bson:"work_count,omitempty" comment:"作品数量"`
	Fans        int    `json:"fans,omitempty" bson:"fans,omitempty" comment:"粉丝数量"`
	Follow      int    `json:"follow,omitempty" bson:"follow,omitempty" comment:"关注数量"`
	Share       int    `json:"share,omitempty" bson:"share,omitempty" comment:"分享数量"`
	PlayView    int    `json:"play_view,omitempty" bson:"play_view,omitempty" comment:"播放数量"` // 用于被多少人点开看了
	Recommend   int    `json:"recommend,omitempty" bson:"recommend,omitempty" comment:"推荐数量"` // 用户被推荐给多少人看了
	Description string `json:"description,omitempty" bson:"description,omitempty" comment:"描述简介"`
}

type Attribute

type Attribute struct {
	GenType   string `json:"gen_type,omitempty" bson:"gen_type,omitempty"`     // 自动生成方式
	GenLen    int    `json:"gen_len,omitempty" bson:"gen_len,omitempty"`       // 生成长度
	GenStat   int    `json:"gen_stat,omitempty" bson:"gen_stat,omitempty"`     // 自动生成起始值
	GenEnd    int    `json:"gen_end,omitempty" bson:"gen_end,omitempty"`       // 自动生成结束值
	AllowEdit bool   `json:"allow_edit,omitempty" bson:"allow_edit,omitempty"` // 生成的值是否允许修改 默认不允许
}

func (*Attribute) RunGen

func (c *Attribute) RunGen() (any, error)

type CbcRequestData

type CbcRequestData struct {
	Query  map[string]interface{} `json:"query"`
	Body   json.RawMessage        `json:"body"`
	Router string                 `json:"router"`
}

type CbcService

type CbcService struct {
	// contains filtered or unexported fields
}

func NewCbcService

func NewCbcService(iv string) *CbcService

func (*CbcService) CbcMainHandler

func (c *CbcService) CbcMainHandler(ctx iris.Context)

func (*CbcService) Decrypt

func (c *CbcService) Decrypt(cipherText string) ([]byte, error)

func (*CbcService) Encrypt

func (c *CbcService) Encrypt(plainText []byte) (string, error)

type GenericsAccount

type GenericsAccount struct {
	ModelBase   `bson:",inline"`
	AccountPass `bson:",inline"`
	AccountCoin `bson:",inline"`
	AccountComm `bson:",inline"`
	// 在mongo中 可以直接使用.法 也就是 platforms.name 就可以传所有数组对象的name包含了的
	Platforms []*AccountPlatform `json:"platforms,omitempty" bson:"platforms,omitempty" comment:"平台信息"`
}

func (*GenericsAccount) BulkInsert

func (s *GenericsAccount) BulkInsert(ctx context.Context, db *qmgo.Collection, accounts ...*GenericsAccount) error

func (*GenericsAccount) Filters

func (s *GenericsAccount) Filters(ctx context.Context, db *qmgo.Collection, filters bson.M) ([]*GenericsAccount, error)

func (*GenericsAccount) GetAccountPass

func (s *GenericsAccount) GetAccountPass() AccountPass

func (*GenericsAccount) GetCoin

func (s *GenericsAccount) GetCoin() AccountCoin

func (*GenericsAccount) GetComm

func (s *GenericsAccount) GetComm() AccountComm

func (*GenericsAccount) GetOne

func (*GenericsAccount) Random

func (s *GenericsAccount) Random(ctx context.Context, db *qmgo.Collection, filters bson.D, count int) ([]*GenericsAccount, error)

func (*GenericsAccount) SetAccountPass

func (s *GenericsAccount) SetAccountPass(pass AccountPass)

func (*GenericsAccount) SetComm

func (s *GenericsAccount) SetComm(comm AccountComm)

func (*GenericsAccount) UpdateOne

func (s *GenericsAccount) UpdateOne(ctx context.Context, db *qmgo.Collection, uid string, pack bson.M) error

type Handler

type Handler[T any] func(ctx iris.Context, query map[string]interface{}, body T)

type HashGenPipe

type HashGenPipe struct {
	Type string   `json:"type,omitempty"` // b58 b62
	Cols []string `json:"cols,omitempty"` // 字段 顺序执行
}

type HttpRequestConfig

type HttpRequestConfig struct {
	Uri        string            `json:"uri,omitempty"`         // 请求地址
	Method     string            `json:"method,omitempty"`      // 请求方法
	PathParams map[string]string `json:"path_params,omitempty"` //
	UrlParams  map[string]any    `json:"url_params,omitempty"`  //
	Body       any               `json:"body,omitempty"`        //
	Headers    map[string]string `json:"headers,omitempty"`     // 请求头设置
	MustCode   int               `json:"must_code,omitempty"`   // 响应码
}

func (*HttpRequestConfig) GetMethod

func (c *HttpRequestConfig) GetMethod() string

func (*HttpRequestConfig) GetMustCode

func (c *HttpRequestConfig) GetMustCode() int

type IAccountGenerics

type IAccountGenerics interface {
	SetAccountPass(pass AccountPass)
	GetAccountPass() AccountPass
	GetCoin() AccountCoin

	GetComm() AccountComm
	SetComm(comm AccountComm)
	// contains filtered or unexported methods
}

type IAccountGenericsFull

type IAccountGenericsFull interface {
	IAccountGenerics
	IAccountShortcut
}

type IAccountShortcut

type IAccountShortcut interface {
	Filters(ctx context.Context, db *qmgo.Collection, filters bson.M) ([]*GenericsAccount, error)
	GetOne(ctx context.Context, db *qmgo.Collection, uid string) (*GenericsAccount, error)
	Random(ctx context.Context, db *qmgo.Collection, filters bson.D, count int) ([]*GenericsAccount, error)
	UpdateOne(ctx context.Context, db *qmgo.Collection, uid string, pack bson.M) error

	BulkInsert(ctx context.Context, db *qmgo.Collection, accounts ...*GenericsAccount) error
	// contains filtered or unexported methods
}

type IMongoBase

type IMongoBase interface {
	GetBase() *ModelBase
	SetBase(raw ModelBase)
}

type IMongoModel

type IMongoModel interface {
	IMongoBase
	GetCollName() string
	SyncIndex() error
}

type JwtCheckDep

type JwtCheckDep struct {
	FlatMap       JwtFlatBase
	Env           string
	Authorization string // Auth头
}

type JwtFlatBase

type JwtFlatBase struct {
	UserId    string `json:"user_id,omitempty"`
	Env       string `json:"env,omitempty"`
	Raw       string `json:"raw,omitempty"`
	LoginTime string `json:"login_time,omitempty"`
}

func (JwtFlatBase) IsShort

func (c JwtFlatBase) IsShort() bool

type JwtGenPipe

type JwtGenPipe struct {
	ExpireDuration time.Duration `json:"expire_duration,omitempty"` // 过期时间 默认24小时
	Strict         bool          `json:"strict,omitempty"`          // 严格模式才执行同一个环境仅单个登录
	Force          bool          `json:"force,omitempty"`           // 强制覆盖 仅在严格模式下启用
}

func (*JwtGenPipe) GetExpire

func (c *JwtGenPipe) GetExpire(defaultTimes ...time.Duration) time.Duration

type JwtHelper

type JwtHelper struct {
	// contains filtered or unexported fields
}

func NewJwtHelper

func NewJwtHelper(rdb rueidis.Client) *JwtHelper

func (*JwtHelper) GenJwtToken

func (c *JwtHelper) GenJwtToken(userId, env string) string

func (*JwtHelper) JwtRedisGenKey

func (c *JwtHelper) JwtRedisGenKey(userId, env string) string

func (*JwtHelper) JwtRedisGetKey

func (c *JwtHelper) JwtRedisGetKey(ctx context.Context, key string) rueidis.RedisResult

func (*JwtHelper) JwtSaveToken

func (c *JwtHelper) JwtSaveToken(ctx context.Context, key string, token string, expired time.Duration) error

func (*JwtHelper) JwtShortRedisGenKey

func (c *JwtHelper) JwtShortRedisGenKey(shortToken string) string

func (*JwtHelper) TokenExtract

func (c *JwtHelper) TokenExtract(token string, m *irisJwt.Middleware) (*JwtFlatBase, error)

TokenExtract jwt验证

type KvValidConfig

type KvValidConfig struct {
	Origin any    `json:"origin,omitempty"` // 原始值
	Op     string `json:"op,omitempty"`     // 操作符
	Value  string `json:"value,omitempty"`  // 值
}

func (*KvValidConfig) Check

func (c *KvValidConfig) Check() (bool, error)

type KvsValidPipe

type KvsValidPipe struct {
	Records []*KvValidConfig `json:"records,omitempty" bson:"records,omitempty"`
}

type LocalCachePipe

type LocalCachePipe struct {
	ExpireDuration time.Duration  `json:"expire_duration,omitempty"` // 过期时间 默认1分钟
	KeyGen         *StrExpand     `json:"key_gen,omitempty"`         // key的来源
	EmptyRaise     bool           `json:"empty_raise,omitempty"`     // 获取时 为空报错
	Values         map[string]any `json:"values,omitempty"`
	DisWriteHeader bool           `json:"dis_write_header,omitempty"` // 不写入header
}

LocalCachePipe 使用 https://github.com/bluele/gcache

func (*LocalCachePipe) GetExpire

func (c *LocalCachePipe) GetExpire() time.Duration

type ModelBase

type ModelBase struct {
	Id       primitive.ObjectID `json:"_id,omitempty" bson:"_id"`
	Uid      string             `json:"uid,omitempty" bson:"uid,omitempty"`
	UpdateAt time.Time          `json:"update_at,omitempty" bson:"update_at,omitempty" comment:"更新时间"`
	CreateAt time.Time          `json:"create_at,omitempty" bson:"create_at,omitempty" comment:"创建时间"`
}

func (*ModelBase) BeforeInsert

func (c *ModelBase) BeforeInsert(ctx context.Context) error

func (*ModelBase) GetBase

func (c *ModelBase) GetBase() *ModelBase

func (*ModelBase) Reset

func (c *ModelBase) Reset()

func (*ModelBase) SetBase

func (c *ModelBase) SetBase(raw ModelBase)

type ModelCtxAddConfig

type ModelCtxAddConfig struct {
	ModelId string `json:"model_id,omitempty"`
}

type ModelDelConfig

type ModelDelConfig struct {
	QueryFilter *ut.QueryFull `json:"query_filter,omitempty"`
	ModelId     string        `json:"model_id,omitempty"`
	RowId       string        `json:"row_id,omitempty"`
}

type ModelGetData

type ModelGetData struct {
	Single        bool `json:"single,omitempty"`          // 仅获取单条 在single的情况下不会返回数量
	GetQueryCount bool `json:"get_query_count,omitempty"` // 返回匹配条数
}

type ModelGetDataDep

type ModelGetDataDep struct {
	ModelId string        `json:"model_id,omitempty"`
	Query   *ut.QueryFull `json:"query,omitempty"`
}

type ModelIndex

type ModelIndex struct {
	FieldName []string `json:"field_name,omitempty" comment:"字段名"` // 支持多级 按.分割 数组是因为可以支持联合索引 这取决于保存的后端是否支持
	Type      string   `json:"type,omitempty" comment:"类型"`        // 2dSphere text unique unique_sparse normal
}

func (*ModelIndex) Gen

func (c *ModelIndex) Gen(v any) mongo.IndexModel

func (*ModelIndex) NewModel2dSphereIndex

func (c *ModelIndex) NewModel2dSphereIndex(fields ...string) *ModelIndex

func (*ModelIndex) NewModelNormalIndex

func (c *ModelIndex) NewModelNormalIndex(fields ...string) *ModelIndex

func (*ModelIndex) NewModelTextIndex

func (c *ModelIndex) NewModelTextIndex(fields ...string) *ModelIndex

func (*ModelIndex) NewModelUniqueIndex

func (c *ModelIndex) NewModelUniqueIndex(fields ...string) *ModelIndex

func (*ModelIndex) NewModelUniqueSparseIndex

func (c *ModelIndex) NewModelUniqueSparseIndex(fields ...string) *ModelIndex

type ModelPutConfig

type ModelPutConfig struct {
	QueryFilter *ut.QueryFull  `json:"query_filter,omitempty"`
	DropKeys    []string       `json:"drop_keys,omitempty"` // 最后的diff还需要丢弃的key
	ModelId     string         `json:"model_id,omitempty"`
	RowId       string         `json:"row_id,omitempty"`
	UpdateTime  bool           `json:"update_time,omitempty"`
	UpdateForce bool           `json:"update_force,omitempty"` // 强行覆盖
	BodyMap     map[string]any `json:"body_map,omitempty"`
}

type ParseResponse

type ParseResponse struct {
	Msg  string `json:"msg,omitempty"`
	Json any    `json:"json,omitempty"`
}

type PipeJwtDep

type PipeJwtDep struct {
	Env    string
	UserId string
}

type QueryParseConfig

type QueryParseConfig struct {
	SearchFields []string          `json:"search_fields,omitempty"`
	Pks          []*ut.Pk          `json:"pks,omitempty"`
	GeoKey       string            `json:"geo_key,omitempty"` // 开启了geo的字段
	InjectAnd    []*ut.Kov         `json:"inject_and,omitempty"`
	InjectOr     []*ut.Kov         `json:"inject_or,omitempty"`
	UrlParams    map[string]string `json:"url_params,omitempty"`
}

QueryParseConfig 所有的fields都是以json tag为准

type RandomPipe

type RandomPipe struct {
	NeedType string  `json:"need_type,omitempty"` // 需要的类型 string int uint float
	Len      int64   `json:"len,omitempty"`       // 对string时有效 string 时必设
	Start    float64 `json:"start,omitempty"`     // 对数字类有效 起始数字
	End      float64 `json:"end,omitempty"`       // 对数字类有效 截止数字
}

type RateLimitPipe

type RateLimitPipe struct {
	// <limit>-<period>
	// * "S": second
	// * "M": minute
	// * "H": hour
	// * "D": day
	//
	// Examples:
	//
	// * 5 reqs/second: "5-S"
	// * 10 reqs/minute: "10-M"
	// * 1000 reqs/hour: "1000-H"
	// * 2000 reqs/day: "2000-D"
	RatePeriod  string     `json:"rate_period,omitempty"`
	Store       string     `json:"store,omitempty"`        // 存储 暂时 memory
	KeyGen      *StrExpand `json:"key_gen,omitempty"`      // 判断key的来源
	WriteHeader bool       `json:"write_header,omitempty"` // 是否把rate状态写入到请求header中
}

type RbacAllowPipe

type RbacAllowPipe struct {
	Sub    string `json:"sub,omitempty"`    // 访问对象不能为空
	Domain string `json:"domain,omitempty"` // 默认自身站点名称
	Obj    string `json:"obj,omitempty"`    // 默认当前访问路径
	Act    string `json:"act,omitempty"`    // 默认当前请求方式
}

RbacAllowPipe 用户是否有权通过此操作 谁(sub)在那个域名(domain)下进行了什么资源(obj)的什么操作(act)

type RbacDomain

type RbacDomain struct {
	E *casbin.Enforcer
	// contains filtered or unexported fields
}

func NewRbacDomain

func NewRbacDomain(redisAddress, password string) (*RbacDomain, error)

func (*RbacDomain) DelRead

func (c *RbacDomain) DelRead(uid string) error

func (*RbacDomain) DelRole

func (c *RbacDomain) DelRole(uid string, role string, domain string) (bool, error)

func (*RbacDomain) DelRoleDefaultDomain

func (c *RbacDomain) DelRoleDefaultDomain(uid string, role string) (bool, error)

func (*RbacDomain) DelRoot

func (c *RbacDomain) DelRoot(uid string) error

func (*RbacDomain) DelStaff

func (c *RbacDomain) DelStaff(uid string) error

func (*RbacDomain) HasRoles

func (c *RbacDomain) HasRoles(uid string, roles []string) bool

func (*RbacDomain) IsStaffOrRoot

func (c *RbacDomain) IsStaffOrRoot(uid string) bool

func (*RbacDomain) SetRead

func (c *RbacDomain) SetRead(uid string) (bool, error)

func (*RbacDomain) SetRole

func (c *RbacDomain) SetRole(uid string, role string, domain string) (bool, error)

func (*RbacDomain) SetRoleDefaultDomain

func (c *RbacDomain) SetRoleDefaultDomain(uid string, role string) (bool, error)

func (*RbacDomain) SetRoot

func (c *RbacDomain) SetRoot(uid string) (bool, error)

func (*RbacDomain) SetStaff

func (c *RbacDomain) SetStaff(uid string) (bool, error)

type RbacGetRolePipe

type RbacGetRolePipe struct {
	Domain string `json:"domain,omitempty"`
	UserId string `json:"user_id,omitempty"`
}

RbacGetRolePipe 获取用户角色操作序列包

type RedisKv

type RedisKv struct {
	Key   string `json:"key,omitempty"`   // key 必须为字符串
	Value string `json:"value,omitempty"` // value 必须为字符串
}

func (*RedisKv) Get

func (c *RedisKv) Get(uid string) ([]string, error)

type RedisOperate

type RedisOperate struct {
	// 最终组合成{Name}: {COMMAND} [{mid:key} {value}] {runAttach:{key | KEY} {value} 模板替换} {EXPIRY} = {ResultType}
	Uid        string     `json:"mid,omitempty"`         // 用户id 自动解析到key上面去
	Type       string     `json:"type,omitempty"`        // 类型 string, list, set, zSet, hash, stream, json? 暂定 可不填
	Command    string     `json:"command,omitempty"`     // 命令 https://redis.io/commands/ 对应上面Type类型 必填
	Kvs        []RedisKv  `json:"kvs,omitempty"`         // key value 对应关系
	Attach     *StrExpand `json:"runAttach,omitempty"`   // 模板key 区分大小写
	Expiry     string     `json:"expiry,omitempty"`      // NX XX GT LT
	ResultType string     `json:"result_type,omitempty"` // 结果类型 推荐直接为空 (string|[]) (int 8 16 32 64|[]|{}) bool (number float 32 64|[]) {}string 为空则any直接输出
	AllowNil   bool       `json:"allow_nil,omitempty"`   // 允许结果为空
}

RedisOperate redis操作 必传uid 一定要注意attach命令需要区分大小写 所有的key都会自动加上 reqUid:key

func (*RedisOperate) Build

func (c *RedisOperate) Build() (*redisAb, error)

func (*RedisOperate) RespParse

func (c *RedisOperate) RespParse(resp rueidis.RedisResult) (result any, err error)

type RedisOperates

type RedisOperates struct {
	Records []*RedisOperate `json:"records,omitempty" bson:"records,omitempty"`
}

type ReqResponse

type ReqResponse struct {
	Type     string         `json:"type,omitempty"`     // 返回值类型 可选 string json 默认json
	Msg      string         `json:"msg,omitempty"`      // string的时候 这个msg存在 则直接吐出
	Items    map[string]any `json:"items,omitempty"`    // 返回值来源
	Excludes []string       `json:"excludes,omitempty"` // 返回值排除 仅type为json时有效
}

type RequestCachePipe

type RequestCachePipe struct {
	CacheTime  time.Duration     `json:"cache_time,omitempty"` // 不传 默认1分钟
	AttachData map[string]string `json:"attach_data,omitempty"`
}

func (*RequestCachePipe) GetCacheKey

func (c *RequestCachePipe) GetCacheKey(ctx iris.Context) (string, error)

func (*RequestCachePipe) GetCacheTime

func (c *RequestCachePipe) GetCacheTime() time.Duration

type RuleValidate

type RuleValidate struct {
	Key      string `json:"key,omitempty"`
	Value    any    `json:"value,omitempty"`
	Rules    string `json:"rules,omitempty"`     // 规则 看上面
	NeedType string `json:"need_type,omitempty"` // 类型转换 可为空
}

RuleValidate 使用这个库 https://github.com/gookit/validate/blob/master/README.zh-CN.md 格式是这样的 required|int|min:1|max:99 处理方法为

type RulesValidate

type RulesValidate struct {
	Record []*RuleValidate `json:"record,omitempty"`
}

func (*RulesValidate) Valid

func (c *RulesValidate) Valid(data map[string]any) ValidResult

type RunResp

type RunResp[T any] struct {
	Result       T      // 执行结果
	Msg          string // 错误说明 有说明则返回说明
	Err          error  // 错误
	ReqCode      int    // 请求状态码 权重在pipeline定义的errCode之后
	BusinessCode int    // 业务code 仅在错误时有则会返回
	IsBreak      bool   // 是否中断之后的执行
}

RunResp 操作序列执行结果

func NewPipeErr

func NewPipeErr[T any](err error) *RunResp[T]

func NewPipeErrMsg

func NewPipeErrMsg[T any](msg string, err error) *RunResp[T]

func NewPipeResult

func NewPipeResult[T any](result T) *RunResp[T]

func NewPipeResultErr

func NewPipeResultErr[T any](result T, err error) *RunResp[T]

func (*RunResp[T]) RaiseError

func (c *RunResp[T]) RaiseError(ctx iris.Context)

func (*RunResp[T]) Return

func (c *RunResp[T]) Return(ctx iris.Context)

func (*RunResp[T]) ReturnSuccess

func (c *RunResp[T]) ReturnSuccess(ctx iris.Context)

func (*RunResp[T]) SetBreak

func (c *RunResp[T]) SetBreak(b bool) *RunResp[T]

func (*RunResp[T]) SetBusinessCode

func (c *RunResp[T]) SetBusinessCode(businessCode int) *RunResp[T]

func (*RunResp[T]) SetReqCode

func (c *RunResp[T]) SetReqCode(reqCode int) *RunResp[T]

type RunnerContext

type RunnerContext[T any, P any, D any, R any] struct {
	Key  string `json:"key,omitempty"`
	Name string `json:"name,omitempty"`
	Desc string `json:"desc,omitempty"`
	// contains filtered or unexported fields
}

RunnerContext 运行器上下文 T 是原始传入值 运行的默认值 P 是执行传入的参数 运行的配置 D 是db 运行的依赖 R 执行结果类型

func (*RunnerContext[T, P, D, R]) NewPipeErr

func (c *RunnerContext[T, P, D, R]) NewPipeErr(err error) *RunResp[R]

func (*RunnerContext[T, P, D, R]) Run

func (c *RunnerContext[T, P, D, R]) Run(ctx iris.Context, origin T, params P, db D, more ...any) *RunResp[R]

func (*RunnerContext[T, P, D, R]) SetDesc

func (c *RunnerContext[T, P, D, R]) SetDesc(desc string) *RunnerContext[T, P, D, R]

func (*RunnerContext[T, P, D, R]) SetKey

func (c *RunnerContext[T, P, D, R]) SetKey(key string) *RunnerContext[T, P, D, R]

func (*RunnerContext[T, P, D, R]) SetName

func (c *RunnerContext[T, P, D, R]) SetName(name string) *RunnerContext[T, P, D, R]

type SchemaValidConfig

type SchemaValidConfig struct {
	Schema *jsonschema.Schema `json:"schema,omitempty"` // 验证器 使用 schema 进行验证
}

type SmsClient

type SmsClient struct {
	// contains filtered or unexported fields
}

func NewDefaultSmsClient

func NewDefaultSmsClient(rdb rueidis.Client) *SmsClient

func NewSmsClient

func NewSmsClient(secretId, secretKey, sign, appId string, rdb rueidis.Client) *SmsClient

func (*SmsClient) DelKey

func (s *SmsClient) DelKey(ctx context.Context, mobile string)

DelKey 删除 key 让code验证

func (*SmsClient) Send

func (s *SmsClient) Send(ctx context.Context, templateID string, mobile string) (string, error)

Send 这个是发送的登录验证码

func (*SmsClient) SendBeforeCheck

func (s *SmsClient) SendBeforeCheck(ctx context.Context, templateId string, mobile string) (string, error)

func (*SmsClient) Valid

func (s *SmsClient) Valid(ctx context.Context, mobile, code string) bool

type SmsPipe

type SmsPipe struct {
	Mobile     string `json:"mobile,omitempty" bson:"mobile,omitempty"`
	TemplateId string `json:"template_id,omitempty" bson:"template_id,omitempty"`
	Code       string `json:"code,omitempty" bson:"code,omitempty"`
}

type StrExpand

type StrExpand struct {
	Key    string        `json:"key,omitempty"`
	KeyMap []StrTemplate `json:"key_map,omitempty"`
}

StrExpand 字符串展开 字符串模板

func (*StrExpand) Build

func (c *StrExpand) Build() (string, error)

type StrTemplate

type StrTemplate struct {
	VarName string `json:"var_name,omitempty"`
	Value   any    `json:"value,omitempty"`
}

type SwipeItem

type SwipeItem struct {
	Id string    `json:"board"`
	C  int8      `json:"c"` // 随机参数数量
	N  bool      `json:"n"` // true 参数在请求包中传递+号  false 参数在header中传递
	P  string    `json:"p"` // 前缀
	T  time.Time `json:"t"` // 获取时间
	X  int       `json:"x"` // 滑块中心位置
	Y  int       `json:"y"` // 滑块中心位置
	B  int       `json:"b"` // 滑块大小
}

func (*SwipeItem) ParseStr

func (c *SwipeItem) ParseStr(raw string) error

func (*SwipeItem) ToString

func (c *SwipeItem) ToString() string

type SwipeValid

type SwipeValid struct {
	Sid          string    `json:"sid,omitempty"`
	RefreshCount int       `json:"refresh_count,omitempty"` // 刷新次数
	X            int64     `json:"x,omitempty"`             // 停止时的x 滑块左侧上角
	Y            int64     `json:"y,omitempty"`             // 停止时的y 滑块左侧上角
	T            time.Time `json:"t,omitempty"`             // 滑动开始的时间
	Te           time.Time `json:"te,omitempty"`            // 滑动结束的时间
	S            float64   `json:"s,omitempty"`             // 拖动速度
	N            float64   `json:"n,omitempty"`             // 归一化 拖动X平均值波动值最高
	Nm           float64   `json:"nm,omitempty"`            // 归一化 拖动X平均值波动值最低
}

type SwipeValidCode

type SwipeValidCode struct {
	RandomCount int8      `json:"random_count,omitempty"` //
	Prefix      string    `json:"Prefix,omitempty"`       // 前缀
	EnableTime  time.Time `json:"enable_time,omitempty"`  // 生效时间
	ExpireSec   int64     `json:"expire_sec,omitempty"`   // 过期秒数
	// contains filtered or unexported fields
}

SwipeValidCode 滑块验证码实例

func NewSwipeValidInst

func NewSwipeValidInst(rdb rueidis.Client) *SwipeValidCode

func (*SwipeValidCode) BlockSize

func (c *SwipeValidCode) BlockSize(half bool) int

func (*SwipeValidCode) Check

func (c *SwipeValidCode) Check(ctx iris.Context, raw string) (*SwipeValid, error)

func (*SwipeValidCode) Gen

func (c *SwipeValidCode) Gen(ctx context.Context) (*SwipeItem, error)

Gen 生成滑块要素并存入redis

func (*SwipeValidCode) RandomBlockX

func (c *SwipeValidCode) RandomBlockX() int

func (*SwipeValidCode) RandomBlockY

func (c *SwipeValidCode) RandomBlockY() int

func (*SwipeValidCode) SetExpireSec

func (c *SwipeValidCode) SetExpireSec(newSec int64)

func (*SwipeValidCode) SetPrefix

func (c *SwipeValidCode) SetPrefix(prefix string)

func (*SwipeValidCode) SetRandomCount

func (c *SwipeValidCode) SetRandomCount(newCount int8)

type ValidResult

type ValidResult struct {
	Pass bool   `json:"pass,omitempty"`
	Msg  string `json:"msg,omitempty"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL