1 Star 0 Fork 0

h79 / gothird

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
mgr.go 7.59 KB
一键复制 编辑 原始数据 按行查看 历史
huqiuyun 提交于 2024-01-20 17:38 . secret changed
package token
import (
"encoding/gob"
"fmt"
"gitee.com/h79/gothird/token/access"
"gitee.com/h79/gothird/token/validate"
"gitee.com/h79/goutils/common/config"
"gitee.com/h79/goutils/common/logger"
"gitee.com/h79/goutils/common/system"
"os"
"path/filepath"
"sync"
"time"
)
type FUpdate struct {
fg int
ty string
}
type AppMgr struct {
path string
saveAt time.Duration
fUpdate chan FUpdate
mu sync.Mutex
apps map[string]*AppItem //[id] 组合
ridMu sync.Mutex
realIds map[string]*RealId //type 不同业务
}
var (
mgr *AppMgr
once sync.Once
rootPath string
appPath string
realIdFileName string
)
func initPath() {
rootPath = fmt.Sprintf("%s/token", config.GetDataPath())
appPath = fmt.Sprintf("%s/apps", rootPath)
if err := checkPath(appPath); err != nil {
panic(err)
}
realIdFileName = rootPath + "/realid.gob"
}
func Mgr() *AppMgr {
once.Do(func() {
initPath()
mgr = &AppMgr{
saveAt: time.Minute * 5,
fUpdate: make(chan FUpdate, 20),
apps: make(map[string]*AppItem, 0),
realIds: make(map[string]*RealId, 0),
}
system.ChildRunning(mgr.check)
})
return mgr
}
func (m *AppMgr) AddToken(id string, app *AppItem) {
m.mu.Lock()
if it, ok := m.apps[id]; ok {
secretIf := it.App.Secret != app.App.Secret
if secretIf {
it.changeSecret(app.App.Secret)
}
m.mu.Unlock()
logger.W("Token", "Add is existed and ignored for id= '%s', app= '%+v', secretIf= %v", id, app.App.String(), secretIf)
return
}
m.mu.Unlock()
m.addToken(id, app)
}
func (m *AppMgr) addToken(id string, app *AppItem) {
m.mu.Lock()
m.apps[id] = app
m.mu.Unlock()
m.ridMu.Lock()
rid, ok := m.realIds[app.App.Type]
if !ok {
rid = &RealId{
ids: make(map[string]string, 0),
}
go rid.load()
m.realIds[app.App.Type] = rid
}
m.ridMu.Unlock()
go func(app *AppItem) {
app.load()
app.start()
}(app)
logger.D("Token", "Add for id= '%s', app= '%+v', path= '%s'", id, app.App.String(), app.Path())
}
func (m *AppMgr) HasToken(id string) bool {
_, err := m.getApp(id)
if err != nil {
return false
}
return true
}
func (m *AppMgr) DeleteToken(id string) error {
m.mu.Lock()
defer m.mu.Unlock()
if _, x := m.apps[id]; x {
delete(m.apps, id)
return nil
}
return fmt.Errorf("not found token for id= '%s'", id)
}
func (m *AppMgr) GetToken(id string) (Token, error) {
if ap, err := m.getApp(id); err == nil {
return ap.tk, nil
}
return nil, fmt.Errorf("not found token for id= '%s'", id)
}
func (m *AppMgr) AddRealId(realId []string, id string, ty string) error {
if len(realId) == 0 {
return ErrParam
}
m.ridMu.Lock()
rid, ok := m.realIds[ty]
m.ridMu.Unlock()
if !ok {
return fmt.Errorf("not found real id for type= '%s'", ty)
}
rid.Add(realId, id)
m.fUpdate <- FUpdate{ty: ty, fg: fReadId}
return nil
}
func (m *AppMgr) GetRealId(ty string, realId string) (string, bool) {
m.ridMu.Lock()
rid, ok := m.realIds[ty]
m.ridMu.Unlock()
if !ok {
return "", false
}
return rid.Get(realId)
}
func (m *AppMgr) DeleteRealId(ty string, realId string) error {
m.ridMu.Lock()
rid, ok := m.realIds[ty]
m.ridMu.Unlock()
if ok {
if rid.Delete(realId) {
m.fUpdate <- FUpdate{ty: ty, fg: fReadId}
return nil
}
}
return fmt.Errorf("not found real id for type= '%s',realId= '%s'", ty, realId)
}
func (m *AppMgr) CreateChild(parent Token, info *Child, service Service) (Token, error) {
if len(info.Id) == 0 {
return nil, ErrParam
}
app, er := m.getApp(parent.GetId())
if er != nil {
return nil, er
}
if info.Id == parent.GetId() {
app.changeSecret(info.Secret)
return app.tk, nil
}
child, err := m.getApp(info.Id)
if err == nil {
child.changeSecret(info.Secret)
return child.tk, nil
}
tk := parent.CreateChild(&info.App, service)
child = newAppItem(&info.App, tk, info.VMap, func(conf *Config) {
*conf = app.conf
})
m.addToken(info.Id, child)
m.fUpdate <- FUpdate{fg: fApp}
return tk, nil
}
func (m *AppMgr) SetAccessToken(id string, acs access.Token) string {
if acs == nil {
return ""
}
v := acs.GetAccessToken()
app, err := m.getApp(id)
if err != nil {
logger.E("Token", "SetAccessToken failure ,id= %s, err= %s", id, err)
return v.Data
}
if v.IsValidOf() {
ex := validate.New(NAccessToken, v.Data, v.ExpireIn)
app.write(ex.Key, ex)
}
v1 := acs.GetRefAccessToken()
if v1.IsValidOf() {
ex := validate.New(NRefreshToken, v1.Data, v1.ExpireIn)
app.write(ex.Key, ex)
}
if v.IsValidOf() || v1.IsValidOf() {
app.itemUpdated(fVMap)
}
return v.Data
}
func (m *AppMgr) Write(id string, key string, v *validate.Data) error {
app, err := m.getApp(id)
if err != nil {
return err
}
app.write(key, v)
app.itemUpdated(fVMap)
return nil
}
func (m *AppMgr) Read(id string, key string) (validate.Data, error) {
app, err := m.getApp(id)
if err != nil {
return validate.Data{}, err
}
v := app.read(key)
if v.IsValid() {
if v.IsExpired() {
logger.W("Token", "key is expired, id=%s, appId= %s, key= %s", id, app.App.AppId, key)
return validate.Data{}, ErrTokenExpired
}
return *v, nil
}
logger.W("Token", "key is not found, id=%s, appId= %s, key= %s", id, app.App.AppId, key)
return validate.Data{}, fmt.Errorf("not found for key= '%s'", key)
}
func (m *AppMgr) Clear(id string, key string) error {
app, err := m.getApp(id)
if err != nil {
return err
}
if _, er := app.clear(key); er != nil {
return er
}
app.itemUpdated(fVMap)
return nil
}
func (m *AppMgr) ChangeSecret(id string, secret string) error {
m.mu.Lock()
if app, found := m.apps[id]; found {
app.changeSecret(secret)
m.mu.Unlock()
return nil
}
m.mu.Unlock()
return fmt.Errorf("not found app for id= '%s'", id)
}
func (m *AppMgr) Save(async bool) {
if async {
m.fUpdate <- FUpdate{fg: fAll}
} else {
m.saveApp()
m.saveRealId("")
}
}
func (m *AppMgr) LoadApp() []App {
files, err := os.ReadDir(appPath)
if err != nil {
logger.E("Token", "Load failure, err=%s", err)
return nil
}
var apps []App
for _, fi := range files {
if fi.IsDir() {
continue
}
if filepath.Ext(fi.Name()) != ".gob" {
continue
}
filename := fmt.Sprintf("%s/%s", appPath, fi.Name())
if er := loadFile(filename, func(de *gob.Decoder) error {
info := App{}
if er := de.Decode(&info); er != nil {
return er
}
apps = append(apps, info)
logger.D("Token", "Load app= %s", info.String())
return nil
}); er != nil {
logger.E("Token", "Load failure, filename=%s, err= %s", filename, err)
}
}
return apps
}
func (m *AppMgr) getApp(id string) (*AppItem, error) {
m.mu.Lock()
if it, found := m.apps[id]; found {
m.mu.Unlock()
return it, nil
}
m.mu.Unlock()
return nil, fmt.Errorf("not found app for id= '%s'", id)
}
func (m *AppMgr) check() {
sys := system.Exit()
minute := time.NewTicker(m.saveAt)
for {
select {
case <-minute.C:
m.saveApp()
m.saveRealId("")
case f := <-m.fUpdate:
if f.fg == fAll {
m.saveApp()
m.saveRealId("")
}
if f.fg == fReadId {
m.saveRealId(f.ty)
}
if f.fg == fApp {
m.saveApp()
}
case <-sys.Done():
m.saveApp()
m.saveRealId("")
return
}
}
}
func (m *AppMgr) saveApp() {
if err := checkPath(appPath); err != nil {
return
}
var (
apps []*AppItem
)
m.mu.Lock()
for _, ap := range m.apps {
apps = append(apps, ap)
}
m.mu.Unlock()
for i := range apps {
apps[i].save()
}
}
func (m *AppMgr) saveRealId(ty string) {
var (
realIds []*RealId
)
if len(ty) > 0 {
m.ridMu.Lock()
rid, ok := m.realIds[ty]
m.ridMu.Unlock()
if ok {
rid.save()
}
return
}
m.ridMu.Lock()
for _, rid := range m.realIds {
realIds = append(realIds, rid)
}
m.ridMu.Unlock()
for i := range realIds {
realIds[i].save()
}
}
1
https://gitee.com/h79/gothird.git
git@gitee.com:h79/gothird.git
h79
gothird
gothird
v1.8.101

搜索帮助