feat:完善项目

This commit is contained in:
henry
2021-09-28 11:47:19 +08:00
commit da7b3130fe
167 changed files with 456676 additions and 0 deletions

235
app/service/auth.go Normal file
View File

@ -0,0 +1,235 @@
package service
import (
"errors"
"fmt"
casbin "github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
gormadapter "github.com/casbin/gorm-adapter/v3"
"gorm.io/gorm"
)
type (
Auth struct {
enforcer *casbin.Enforcer
}
// Permission 权限信息
Permission struct {
Identity *Identity // 身份信息
Roles []string // 角色
Request []*AuthRequest
}
// Identity 身份信息
Identity struct {
Tenant string // 平台-小区
User string // 用户唯一标识
}
AuthRequest struct {
Url string
Method string
}
IdentityPermission func(tenant, user string) *Permission
)
var auth *Auth
// adapter 规则
var adapter = map[string]func(params ...interface{}) interface{}{
"mysql": adapterForOrm, "sqlite": adapterForOrm,
}
// adapterForOrm
func adapterForOrm(params ...interface{}) interface{} {
db := params[0].(*gorm.DB)
obj := params[1].(string)
adapter, _ := gormadapter.NewAdapterByDBUseTableName(db, "", obj)
return adapter
}
// Register 注册权限
// 多平台 admin tenant1, data1, read (角色-域-用户-事件)
// p admin tenant1, data1, read (角色-域-用户-事件)
// g alice, admin, tenant1 (用户-角色-域)
func (this *Auth) Register() func(mode string, params ...interface{}) interface{} {
return func(mode string, params ...interface{}) interface{} {
m := model.NewModel()
m.AddDef("r", "r", "sub, dom, obj, act")
m.AddDef("p", "p", "sub, dom, obj, act")
m.AddDef("g", "g", "_, _, _")
m.AddDef("e", "e", "some(where (p.eft == allow))")
m.AddDef("m", "m", "g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act")
a, has := adapter[mode]
if has {
this.enforcer, _ = casbin.NewEnforcer(m, a(params...))
this.enforcer.EnableAutoSave(true)
} else {
this.enforcer, _ = casbin.NewEnforcer(m)
}
auth = this
return nil
}
}
// tenantIdentity 平台租户信息
func (this *Identity) tenantIdentity() string {
return fmt.Sprintf("%s%s", "t_", this.Tenant)
}
// userIdentity 用户身份信息
func (this *Identity) userIdentity() string {
return fmt.Sprintf("%s%s", "u_", this.User)
}
// roleIdentity 角色身份信息
func (this *Permission) roleIdentity() []string {
roles := make([]string, 0)
for _, v := range this.Roles {
roles = append(roles, fmt.Sprintf("%s%s", "r_", v))
}
return roles
}
// AddRoleForUser 增加用户角色
func (this *Permission) AddRoleForUser() (bool, error) {
if this.Roles == nil || len(this.Roles) <= 0 {
return false, errors.New("无角色信息")
}
for _, role := range this.roleIdentity() {
if _, err := auth.enforcer.AddRoleForUser(this.Identity.userIdentity(), role, this.Identity.tenantIdentity()); err != nil {
return false, err
}
}
return true, nil
}
// DeleteRoleForUser 删除用户角色
//func (this *Permission) DeleteRoleForUser() (bool, error) {
// if this.Roles == nil || len(this.Roles) <= 0 {
// return false, errors.New("角色信息不存在")
// }
// for _, role := range this.roleIdentity() {
// status, err := auth.enforcer.DeleteRoleForUser(this.Identity.userIdentity(), role, this.Identity.tenantIdentity())
// if err != nil {
// return false, err
// } else if !status {
// return false, errors.New("删除失败")
// }
// }
// return true, nil
//}
// DeleteRolesForUser 删除用户所有角色
func (this *Permission) DeleteRolesForUser(allTenant bool) (bool, error) {
if allTenant {
return auth.enforcer.DeleteRolesForUser(this.Identity.userIdentity())
}
return auth.enforcer.DeleteRolesForUser(this.Identity.userIdentity(), this.Identity.tenantIdentity())
}
//// AddPolicy 增加规则
//func (this *Permission) AddPolicy() (bool, error) {
// if this.Request == nil || len(this.Request) <= 0 {
// return false, errors.New("请求事件错误")
// }
// return auth.enforcer.AddPolicy(this.roleIdentity()[0], this.Identity.tenantIdentity(), this.Request[0].Url, this.Request[0].Method)
//}
// AddPolicies TODO:增加多个规则
func (this *Permission) AddPolicies() (bool, error) {
if this.Request == nil || len(this.Request) <= 0 {
return false, errors.New("请求事件错误")
}
rules := make([][]string, 0)
for _, s := range this.Request {
rules = append(rules, []string{
this.roleIdentity()[0], this.Identity.tenantIdentity(), s.Url, s.Method,
})
}
return auth.enforcer.AddPolicies(rules)
}
//// RemovePolicy TODO:删除规则
//func (this *Permission) RemovePolicy() (bool, error) {
// if this.Request == nil || len(this.Request) <= 0 {
// return false, errors.New("请求事件错误")
// }
// return auth.enforcer.RemovePolicy(this.roleIdentity()[0], this.Identity.tenantIdentity(), this.Request[0].Url, this.Request[0].Method)
//}
//
//// RemovePolicies 删除多个规则
//func (this *Permission) RemovePolicies() (bool, error) {
// rules := make([][]string, 0)
//
// for _, s := range this.Request {
// rules = append(rules, []string{
// this.roleIdentity()[0], this.Identity.tenantIdentity(), s.Url, s.Method,
// })
// }
// return auth.enforcer.RemovePolicies(rules)
//}
// RemoveRolePolicy 删除角色的所有规则
func (this *Permission) RemoveRolePolicy() (bool, error) {
if this.Roles == nil || len(this.Roles) <= 0 {
return false, errors.New("角色信息不存在")
}
return auth.enforcer.RemoveFilteredPolicy(0, this.roleIdentity()[0], this.Identity.tenantIdentity())
}
// RemoveNamedGroupingPolicies 删除租户下角色的权限
func (this *Permission) RemoveNamedGroupingPolicies() (bool, error) {
rules := make([][]string, 0)
roles := this.roleIdentity()
for _, role := range roles {
rule := make([]string, 0)
for _, request := range this.Request {
rule = append(rule, role, this.Identity.tenantIdentity(), request.Url, request.Method)
}
rules = append(rules, rule)
}
return auth.enforcer.RemoveNamedGroupingPolicies("g", rules)
}
// RemoveFilteredGroupingPolicy 删除组权限规则
func (this *Permission) RemoveFilteredGroupingPolicy() (bool, error) {
return auth.enforcer.RemoveFilteredGroupingPolicy(0, this.Identity.tenantIdentity())
}
// HasPolicy 检查访问权限
func (this *Permission) Enforce() (bool, error) {
if this.Request == nil || len(this.Request) <= 0 {
return false, errors.New("请求事件错误")
}
return auth.enforcer.Enforce(this.Identity.userIdentity(), this.Identity.tenantIdentity(), this.Request[0].Url, "*")
}
// NewAuth
func NewAuth() *Auth {
return &Auth{}
}
// NewPermission
func NewPermission(roles []string, act ...*AuthRequest) IdentityPermission {
return func(tenant, user string) *Permission {
return &Permission{
Identity: &Identity{
Tenant: tenant,
User: user,
},
Roles: roles,
Request: act,
}
}
}

106
app/service/captcha.go Normal file
View File

@ -0,0 +1,106 @@
package service
import (
"errors"
"github.com/mojocn/base64Captcha"
)
type Param struct {
obj interface{}
}
type CaptchaInfo struct {
Key string `json:"key"`
Captcha string `json:"captcha"`
}
type CaptchaType string
const (
CaptchaTypeForDefault CaptchaType = "default"
CaptchaTypeForAudio CaptchaType = "audio"
CaptchaTypeForString CaptchaType = "string"
CaptchaTypeForMath CaptchaType = "math"
CaptchaTypeForChinese CaptchaType = "chinese"
)
var drivers = map[CaptchaType]func() base64Captcha.Driver{
CaptchaTypeForDefault: captchaForDigit,
CaptchaTypeForAudio: captchaForAudio,
CaptchaTypeForString: captchaForString,
CaptchaTypeForMath: captchaForMath,
CaptchaTypeForChinese: captchaForChinese,
}
var store = base64Captcha.DefaultMemStore
func captchaForDigit() base64Captcha.Driver {
drive := new(base64Captcha.DriverDigit)
drive.Width = 100
drive.Height = 40
drive.DotCount = 80
drive.Length = 6
drive.MaxSkew = 0.7
return drive
}
func captchaForAudio() base64Captcha.Driver {
drive := new(base64Captcha.DriverAudio)
drive.Language = "zh"
drive.Length = 4
return drive
}
func captchaForString() base64Captcha.Driver {
drive := new(base64Captcha.DriverString)
drive.Width = 100
drive.Width = 40
drive.Source = "设想,你在,处理,消费者,的音,频输,出音,频可,能无,论什,么都,没有,任何,输出,或者,它可,能是,单声道,立体声,或是,环绕立,体声的,不想要,的值"
drive.Length = 2
return drive.ConvertFonts()
}
func captchaForMath() base64Captcha.Driver {
drive := new(base64Captcha.DriverMath)
drive.Width = 100
drive.Height = 40
drive.NoiseCount = 1
return drive.ConvertFonts()
}
func captchaForChinese() base64Captcha.Driver {
drive := new(base64Captcha.DriverChinese)
drive.Width = 100
drive.Width = 40
drive.Source = "1234567890qwertyuioplkjhgfdsazxcvbnm"
drive.Length = 4
return drive.ConvertFonts()
}
func (this *Param) Create() (*CaptchaInfo, error) {
obj := this.obj.(CaptchaType)
drive, has := drivers[obj]
if !has {
return nil, errors.New("参数异常")
}
c := base64Captcha.NewCaptcha(drive(), store)
key, captcha, err := c.Generate()
if err != nil {
return nil, err
}
return &CaptchaInfo{Key: key, Captcha: captcha}, nil
}
func (this *Param) Validate() bool {
obj := this.obj.(*CaptchaInfo)
return store.Verify(obj.Key, obj.Captcha, true)
}
func Captcha(obj interface{}) *Param {
return &Param{obj: obj}
}

56
app/service/eventhub.go Normal file
View File

@ -0,0 +1,56 @@
package service
import (
"sync"
)
// listener 监听
type listener struct {
handler ListenerHandle
}
// listeners 监听器
type listeners struct {
listener map[interface{}]*listener
mutex *sync.RWMutex
}
// ListenerHandle 监听事件
type ListenerHandle interface {
Handle(args ...interface{})
}
// listenerObject 监听器
var listenerObject = &listeners{
listener: make(map[interface{}]*listener, 0),
mutex: new(sync.RWMutex),
}
// Subscribe 注册事件
func Subscribe(prefix interface{}, handler ListenerHandle) {
listenerObject.mutex.Lock()
defer listenerObject.mutex.Unlock()
listenerObject.listener[prefix] = &listener{handler: handler}
}
// Publish 推送事件
func Publish(prefix interface{}, args ...interface{}) {
listenerObject.mutex.RLock()
defer listenerObject.mutex.RUnlock()
listener, has := listenerObject.listener[prefix]
if !has {
return
}
listener.handler.Handle(args...)
}
// Unsubscribe 取消监听
func Unsubscribe(prefix interface{}) {
listenerObject.mutex.Lock()
defer listenerObject.mutex.Unlock()
_, has := listenerObject.listener[prefix]
if !has {
return
}
delete(listenerObject.listener, prefix)
}

28
app/service/session.go Normal file
View File

@ -0,0 +1,28 @@
package service
import (
"SciencesServer/utils"
"encoding/json"
)
type Session struct {
UID uint64 `json:"uid"` // 唯一标识ID
Token string `json:"token"` // token
Name string `json:"name"` // 名称
Mobile string `json:"mobile"` // 手机号码
IsAdmin bool `json:"is_admin"` // 是否超管
TenantID uint64 `json:"tenant_id"` // 租户ID
TenantKey string `json:"tenant_key"` // 租户标识,用来区别分库管理
}
func (this *Session) MarshalBinary() ([]byte, error) {
return json.Marshal(this)
}
func (this *Session) UnmarshalBinary(data []byte) error {
return utils.FromJSONBytes(data, this)
}
func NewSession() *Session {
return &Session{}
}