mirror of
https://github.com/TeaOSLab/EdgeAPI.git
synced 2025-11-06 10:00:24 +08:00
[API节点]显示API节点运行日志 [用户]增加可用功能控制、AccessKey管理
This commit is contained in:
71
internal/db/models/sub_user_dao.go
Normal file
71
internal/db/models/sub_user_dao.go
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
SubUserStateEnabled = 1 // 已启用
|
||||||
|
SubUserStateDisabled = 0 // 已禁用
|
||||||
|
)
|
||||||
|
|
||||||
|
type SubUserDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewSubUserDAO() *SubUserDAO {
|
||||||
|
return dbs.NewDAO(&SubUserDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeSubUsers",
|
||||||
|
Model: new(SubUser),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*SubUserDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedSubUserDAO *SubUserDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedSubUserDAO = NewSubUserDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启用条目
|
||||||
|
func (this *SubUserDAO) EnableSubUser(id uint32) error {
|
||||||
|
_, err := this.Query().
|
||||||
|
Pk(id).
|
||||||
|
Set("state", SubUserStateEnabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 禁用条目
|
||||||
|
func (this *SubUserDAO) DisableSubUser(id uint32) error {
|
||||||
|
_, err := this.Query().
|
||||||
|
Pk(id).
|
||||||
|
Set("state", SubUserStateDisabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找启用中的条目
|
||||||
|
func (this *SubUserDAO) FindEnabledSubUser(id uint32) (*SubUser, error) {
|
||||||
|
result, err := this.Query().
|
||||||
|
Pk(id).
|
||||||
|
Attr("state", SubUserStateEnabled).
|
||||||
|
Find()
|
||||||
|
if result == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result.(*SubUser), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据主键查找名称
|
||||||
|
func (this *SubUserDAO) FindSubUserName(id uint32) (string, error) {
|
||||||
|
return this.Query().
|
||||||
|
Pk(id).
|
||||||
|
Result("name").
|
||||||
|
FindStringCol("")
|
||||||
|
}
|
||||||
5
internal/db/models/sub_user_dao_test.go
Normal file
5
internal/db/models/sub_user_dao_test.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
)
|
||||||
26
internal/db/models/sub_user_model.go
Normal file
26
internal/db/models/sub_user_model.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
// 子用户
|
||||||
|
type SubUser struct {
|
||||||
|
Id uint32 `field:"id"` // ID
|
||||||
|
UserId uint32 `field:"userId"` // 所属主用户ID
|
||||||
|
IsOn uint8 `field:"isOn"` // 是否启用
|
||||||
|
Name string `field:"name"` // 名称
|
||||||
|
Username string `field:"username"` // 用户名
|
||||||
|
Password string `field:"password"` // 密码
|
||||||
|
State uint8 `field:"state"` // 状态
|
||||||
|
}
|
||||||
|
|
||||||
|
type SubUserOperator struct {
|
||||||
|
Id interface{} // ID
|
||||||
|
UserId interface{} // 所属主用户ID
|
||||||
|
IsOn interface{} // 是否启用
|
||||||
|
Name interface{} // 名称
|
||||||
|
Username interface{} // 用户名
|
||||||
|
Password interface{} // 密码
|
||||||
|
State interface{} // 状态
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSubUserOperator() *SubUserOperator {
|
||||||
|
return &SubUserOperator{}
|
||||||
|
}
|
||||||
1
internal/db/models/sub_user_model_ext.go
Normal file
1
internal/db/models/sub_user_model_ext.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package models
|
||||||
111
internal/db/models/user_access_key_dao.go
Normal file
111
internal/db/models/user_access_key_dao.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
"github.com/iwind/TeaGo/Tea"
|
||||||
|
"github.com/iwind/TeaGo/dbs"
|
||||||
|
"github.com/iwind/TeaGo/rands"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
UserAccessKeyStateEnabled = 1 // 已启用
|
||||||
|
UserAccessKeyStateDisabled = 0 // 已禁用
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserAccessKeyDAO dbs.DAO
|
||||||
|
|
||||||
|
func NewUserAccessKeyDAO() *UserAccessKeyDAO {
|
||||||
|
return dbs.NewDAO(&UserAccessKeyDAO{
|
||||||
|
DAOObject: dbs.DAOObject{
|
||||||
|
DB: Tea.Env,
|
||||||
|
Table: "edgeUserAccessKeys",
|
||||||
|
Model: new(UserAccessKey),
|
||||||
|
PkName: "id",
|
||||||
|
},
|
||||||
|
}).(*UserAccessKeyDAO)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SharedUserAccessKeyDAO *UserAccessKeyDAO
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
dbs.OnReady(func() {
|
||||||
|
SharedUserAccessKeyDAO = NewUserAccessKeyDAO()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启用条目
|
||||||
|
func (this *UserAccessKeyDAO) EnableUserAccessKey(id int64) error {
|
||||||
|
_, err := this.Query().
|
||||||
|
Pk(id).
|
||||||
|
Set("state", UserAccessKeyStateEnabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 禁用条目
|
||||||
|
func (this *UserAccessKeyDAO) DisableUserAccessKey(id int64) error {
|
||||||
|
_, err := this.Query().
|
||||||
|
Pk(id).
|
||||||
|
Set("state", UserAccessKeyStateDisabled).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找启用中的条目
|
||||||
|
func (this *UserAccessKeyDAO) FindEnabledUserAccessKey(id int64) (*UserAccessKey, error) {
|
||||||
|
result, err := this.Query().
|
||||||
|
Pk(id).
|
||||||
|
Attr("state", UserAccessKeyStateEnabled).
|
||||||
|
Find()
|
||||||
|
if result == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result.(*UserAccessKey), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建Key
|
||||||
|
func (this *UserAccessKeyDAO) CreateAccessKey(userId int64, description string) (int64, error) {
|
||||||
|
if userId <= 0 {
|
||||||
|
return 0, errors.New("invalid userId")
|
||||||
|
}
|
||||||
|
op := NewUserAccessKeyOperator()
|
||||||
|
op.UserId = userId
|
||||||
|
op.Description = description
|
||||||
|
op.UniqueId = rands.String(16)
|
||||||
|
op.Secret = rands.String(32)
|
||||||
|
op.IsOn = true
|
||||||
|
op.State = UserAccessKeyStateEnabled
|
||||||
|
return this.SaveInt64(op)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找用户所有的Key
|
||||||
|
func (this *UserAccessKeyDAO) FindAllEnabledAccessKeys(userId int64) (result []*UserAccessKey, err error) {
|
||||||
|
_, err = this.Query().
|
||||||
|
State(UserAccessKeyStateEnabled).
|
||||||
|
DescPk().
|
||||||
|
Slice(&result).
|
||||||
|
FindAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查用户的AccessKey
|
||||||
|
func (this *UserAccessKeyDAO) CheckUserAccessKey(userId int64, accessKeyId int64) (bool, error) {
|
||||||
|
return this.Query().
|
||||||
|
Pk(accessKeyId).
|
||||||
|
State(UserAccessKeyStateEnabled).
|
||||||
|
Attr("userId", userId).
|
||||||
|
Exist()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置是否启用
|
||||||
|
func (this *UserAccessKeyDAO) UpdateAccessKeyIsOn(accessKeyId int64, isOn bool) error {
|
||||||
|
if accessKeyId <= 0 {
|
||||||
|
return errors.New("invalid accessKeyId")
|
||||||
|
}
|
||||||
|
_, err := this.Query().
|
||||||
|
Pk(accessKeyId).
|
||||||
|
Set("isOn", isOn).
|
||||||
|
Update()
|
||||||
|
return err
|
||||||
|
}
|
||||||
5
internal/db/models/user_access_key_dao_test.go
Normal file
5
internal/db/models/user_access_key_dao_test.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
)
|
||||||
28
internal/db/models/user_access_key_model.go
Normal file
28
internal/db/models/user_access_key_model.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
// AccessKey
|
||||||
|
type UserAccessKey struct {
|
||||||
|
Id uint32 `field:"id"` // ID
|
||||||
|
UserId uint32 `field:"userId"` // 用户ID
|
||||||
|
SubUserId uint32 `field:"subUserId"` // 子用户ID
|
||||||
|
IsOn uint8 `field:"isOn"` // 是否启用
|
||||||
|
UniqueId string `field:"uniqueId"` // 唯一的Key
|
||||||
|
Secret string `field:"secret"` // 密钥
|
||||||
|
Description string `field:"description"` // 备注
|
||||||
|
State uint8 `field:"state"` // 状态
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserAccessKeyOperator struct {
|
||||||
|
Id interface{} // ID
|
||||||
|
UserId interface{} // 用户ID
|
||||||
|
SubUserId interface{} // 子用户ID
|
||||||
|
IsOn interface{} // 是否启用
|
||||||
|
UniqueId interface{} // 唯一的Key
|
||||||
|
Secret interface{} // 密钥
|
||||||
|
Description interface{} // 备注
|
||||||
|
State interface{} // 状态
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewUserAccessKeyOperator() *UserAccessKeyOperator {
|
||||||
|
return &UserAccessKeyOperator{}
|
||||||
|
}
|
||||||
1
internal/db/models/user_access_key_model_ext.go
Normal file
1
internal/db/models/user_access_key_model_ext.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package models
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
"github.com/TeaOSLab/EdgeAPI/internal/errors"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
"github.com/iwind/TeaGo/Tea"
|
"github.com/iwind/TeaGo/Tea"
|
||||||
@@ -229,3 +230,54 @@ func (this *UserDAO) FindUserClusterId(userId int64) (int64, error) {
|
|||||||
Result("clusterId").
|
Result("clusterId").
|
||||||
FindInt64Col(0)
|
FindInt64Col(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新用户Features
|
||||||
|
func (this *UserDAO) UpdateUserFeatures(userId int64, featuresJSON []byte) error {
|
||||||
|
if userId <= 0 {
|
||||||
|
return errors.New("invalid userId")
|
||||||
|
}
|
||||||
|
if len(featuresJSON) == 0 {
|
||||||
|
featuresJSON = []byte("[]")
|
||||||
|
}
|
||||||
|
_, err := this.Query().
|
||||||
|
Pk(userId).
|
||||||
|
Set("features", featuresJSON).
|
||||||
|
Update()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找用户Features
|
||||||
|
func (this *UserDAO) FindUserFeatures(userId int64) ([]*UserFeature, error) {
|
||||||
|
featuresJSON, err := this.Query().
|
||||||
|
Pk(userId).
|
||||||
|
Result("features").
|
||||||
|
FindStringCol("")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if len(featuresJSON) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
featureCodes := []string{}
|
||||||
|
err = json.Unmarshal([]byte(featuresJSON), &featureCodes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否还存在以及设置名称
|
||||||
|
result := []*UserFeature{}
|
||||||
|
if len(featureCodes) > 0 {
|
||||||
|
for _, featureCode := range featureCodes {
|
||||||
|
f := FindUserFeature(featureCode)
|
||||||
|
if f != nil {
|
||||||
|
result = append(result, &UserFeature{Name: f.Name, Code: f.Code, Description: f.Description})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|||||||
50
internal/db/models/user_features.go
Normal file
50
internal/db/models/user_features.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// 所有功能列表,注意千万不能在运行时进行修改
|
||||||
|
allUserFeatures = []*UserFeature{
|
||||||
|
{
|
||||||
|
Name: "记录访问日志",
|
||||||
|
Code: "server.accessLog",
|
||||||
|
Description: "用户可以开启服务的访问日志",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "转发访问日志",
|
||||||
|
Code: "server.accessLog.forward",
|
||||||
|
Description: "用户可以配置访问日志转发到自定义的API",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "开启WAF",
|
||||||
|
Code: "server.waf",
|
||||||
|
Description: "用户可以开启WAF功能并可以设置黑白名单等",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// 用户功能
|
||||||
|
type UserFeature struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *UserFeature) ToPB() *pb.UserFeature {
|
||||||
|
return &pb.UserFeature{Name: this.Name, Code: this.Code, Description: this.Description}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 所有功能列表
|
||||||
|
func FindAllUserFeatures() []*UserFeature {
|
||||||
|
return allUserFeatures
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询单个功能
|
||||||
|
func FindUserFeature(code string) *UserFeature {
|
||||||
|
for _, feature := range allUserFeatures {
|
||||||
|
if feature.Code == code {
|
||||||
|
return feature
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -17,6 +17,7 @@ type User struct {
|
|||||||
State uint8 `field:"state"` // 状态
|
State uint8 `field:"state"` // 状态
|
||||||
Source string `field:"source"` // 来源
|
Source string `field:"source"` // 来源
|
||||||
ClusterId uint32 `field:"clusterId"` // 集群ID
|
ClusterId uint32 `field:"clusterId"` // 集群ID
|
||||||
|
Features string `field:"features"` // 允许操作的特征
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserOperator struct {
|
type UserOperator struct {
|
||||||
@@ -35,6 +36,7 @@ type UserOperator struct {
|
|||||||
State interface{} // 状态
|
State interface{} // 状态
|
||||||
Source interface{} // 来源
|
Source interface{} // 来源
|
||||||
ClusterId interface{} // 集群ID
|
ClusterId interface{} // 集群ID
|
||||||
|
Features interface{} // 允许操作的特征
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserOperator() *UserOperator {
|
func NewUserOperator() *UserOperator {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/TeaOSLab/EdgeAPI/internal/configs"
|
"github.com/TeaOSLab/EdgeAPI/internal/configs"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/remotelogs"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
"github.com/TeaOSLab/EdgeAPI/internal/rpc/services"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/setup"
|
"github.com/TeaOSLab/EdgeAPI/internal/setup"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||||
@@ -72,12 +73,12 @@ func (this *APINode) Start() {
|
|||||||
go NewNodeStatusExecutor().Listen()
|
go NewNodeStatusExecutor().Listen()
|
||||||
|
|
||||||
// 监听RPC服务
|
// 监听RPC服务
|
||||||
logs.Println("[API_NODE]starting rpc ...")
|
remotelogs.Println("API_NODE", "starting RPC server ...")
|
||||||
|
|
||||||
// HTTP
|
// HTTP
|
||||||
httpConfig, err := apiNode.DecodeHTTP()
|
httpConfig, err := apiNode.DecodeHTTP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("[API_NODE]decode http config: " + err.Error())
|
remotelogs.Error("API_NODE", "decode http config: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isListening := false
|
isListening := false
|
||||||
@@ -86,13 +87,13 @@ func (this *APINode) Start() {
|
|||||||
for _, addr := range listen.Addresses() {
|
for _, addr := range listen.Addresses() {
|
||||||
listener, err := net.Listen("tcp", addr)
|
listener, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("[API_NODE]listening '" + addr + "' failed: " + err.Error())
|
remotelogs.Error("API_NODE", "listening '"+addr+"' failed: "+err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
err := this.listenRPC(listener, nil)
|
err := this.listenRPC(listener, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("[API_NODE]listening '" + addr + "' rpc: " + err.Error())
|
remotelogs.Error("API_NODE", "listening '"+addr+"' rpc: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -104,7 +105,7 @@ func (this *APINode) Start() {
|
|||||||
// HTTPS
|
// HTTPS
|
||||||
httpsConfig, err := apiNode.DecodeHTTPS()
|
httpsConfig, err := apiNode.DecodeHTTPS()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("[API_NODE]decode https config: " + err.Error())
|
remotelogs.Error("API_NODE", "decode https config: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if httpsConfig != nil &&
|
if httpsConfig != nil &&
|
||||||
@@ -122,7 +123,7 @@ func (this *APINode) Start() {
|
|||||||
for _, addr := range listen.Addresses() {
|
for _, addr := range listen.Addresses() {
|
||||||
listener, err := net.Listen("tcp", addr)
|
listener, err := net.Listen("tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("[API_NODE]listening '" + addr + "' failed: " + err.Error())
|
remotelogs.Error("API_NODE", "listening '"+addr+"' failed: "+err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
@@ -130,7 +131,7 @@ func (this *APINode) Start() {
|
|||||||
Certificates: certs,
|
Certificates: certs,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logs.Println("[API_NODE]listening '" + addr + "' rpc: " + err.Error())
|
remotelogs.Error("API_NODE", "listening '"+addr+"' rpc: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
@@ -142,7 +143,7 @@ func (this *APINode) Start() {
|
|||||||
// HTTP接口
|
// HTTP接口
|
||||||
|
|
||||||
if !isListening {
|
if !isListening {
|
||||||
logs.Println("[API_NODE]the api node does have a listening address")
|
remotelogs.Error("API_NODE", "the api node require at least one listening address")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +155,7 @@ func (this *APINode) Start() {
|
|||||||
func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) error {
|
func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) error {
|
||||||
var rpcServer *grpc.Server
|
var rpcServer *grpc.Server
|
||||||
if tlsConfig == nil {
|
if tlsConfig == nil {
|
||||||
logs.Println("[API_NODE]listening http://" + listener.Addr().String() + " ...")
|
remotelogs.Println("API_NODE", "listening http://"+listener.Addr().String()+" ...")
|
||||||
rpcServer = grpc.NewServer()
|
rpcServer = grpc.NewServer()
|
||||||
} else {
|
} else {
|
||||||
logs.Println("[API_NODE]listening https://" + listener.Addr().String() + " ...")
|
logs.Println("[API_NODE]listening https://" + listener.Addr().String() + " ...")
|
||||||
@@ -212,6 +213,7 @@ func (this *APINode) listenRPC(listener net.Listener, tlsConfig *tls.Config) err
|
|||||||
pb.RegisterUserBillServiceServer(rpcServer, &services.UserBillService{})
|
pb.RegisterUserBillServiceServer(rpcServer, &services.UserBillService{})
|
||||||
pb.RegisterUserNodeServiceServer(rpcServer, &services.UserNodeService{})
|
pb.RegisterUserNodeServiceServer(rpcServer, &services.UserNodeService{})
|
||||||
pb.RegisterLoginServiceServer(rpcServer, &services.LoginService{})
|
pb.RegisterLoginServiceServer(rpcServer, &services.LoginService{})
|
||||||
|
pb.RegisterUserAccessKeyServiceServer(rpcServer, &services.UserAccessKeyService{})
|
||||||
err := rpcServer.Serve(listener)
|
err := rpcServer.Serve(listener)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("[API_NODE]start rpc failed: " + err.Error())
|
return errors.New("[API_NODE]start rpc failed: " + err.Error())
|
||||||
@@ -252,11 +254,13 @@ func (this *APINode) autoUpgrade() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 不使用remotelogs(),因为此时还没有启动完成
|
||||||
logs.Println("[API_NODE]upgrade database starting ...")
|
logs.Println("[API_NODE]upgrade database starting ...")
|
||||||
err = setup.NewSQLExecutor(dbConfig).Run()
|
err = setup.NewSQLExecutor(dbConfig).Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("execute sql failed: " + err.Error())
|
return errors.New("execute sql failed: " + err.Error())
|
||||||
}
|
}
|
||||||
|
// 不使用remotelogs
|
||||||
logs.Println("[API_NODE]upgrade database done")
|
logs.Println("[API_NODE]upgrade database done")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package remotelogs
|
package remotelogs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/configs"
|
||||||
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
"github.com/iwind/TeaGo/logs"
|
"github.com/iwind/TeaGo/logs"
|
||||||
"time"
|
"time"
|
||||||
@@ -15,7 +16,10 @@ func init() {
|
|||||||
ticker := time.NewTicker(60 * time.Second)
|
ticker := time.NewTicker(60 * time.Second)
|
||||||
go func() {
|
go func() {
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
// TODO
|
err := uploadLogs()
|
||||||
|
if err != nil {
|
||||||
|
logs.Println("[LOG]" + err.Error())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@@ -24,7 +28,7 @@ func init() {
|
|||||||
func Println(tag string, description string) {
|
func Println(tag string, description string) {
|
||||||
logs.Println("[" + tag + "]" + description)
|
logs.Println("[" + tag + "]" + description)
|
||||||
|
|
||||||
nodeConfig, _ := nodeconfigs.SharedNodeConfig()
|
nodeConfig, _ := configs.SharedAPIConfig()
|
||||||
if nodeConfig == nil {
|
if nodeConfig == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -35,7 +39,7 @@ func Println(tag string, description string) {
|
|||||||
Tag: tag,
|
Tag: tag,
|
||||||
Description: description,
|
Description: description,
|
||||||
Level: "info",
|
Level: "info",
|
||||||
NodeId: nodeConfig.Id,
|
NodeId: nodeConfig.NumberId(),
|
||||||
CreatedAt: time.Now().Unix(),
|
CreatedAt: time.Now().Unix(),
|
||||||
}:
|
}:
|
||||||
default:
|
default:
|
||||||
@@ -47,7 +51,7 @@ func Println(tag string, description string) {
|
|||||||
func Warn(tag string, description string) {
|
func Warn(tag string, description string) {
|
||||||
logs.Println("[" + tag + "]" + description)
|
logs.Println("[" + tag + "]" + description)
|
||||||
|
|
||||||
nodeConfig, _ := nodeconfigs.SharedNodeConfig()
|
nodeConfig, _ := configs.SharedAPIConfig()
|
||||||
if nodeConfig == nil {
|
if nodeConfig == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -58,7 +62,7 @@ func Warn(tag string, description string) {
|
|||||||
Tag: tag,
|
Tag: tag,
|
||||||
Description: description,
|
Description: description,
|
||||||
Level: "warning",
|
Level: "warning",
|
||||||
NodeId: nodeConfig.Id,
|
NodeId: nodeConfig.NumberId(),
|
||||||
CreatedAt: time.Now().Unix(),
|
CreatedAt: time.Now().Unix(),
|
||||||
}:
|
}:
|
||||||
default:
|
default:
|
||||||
@@ -70,7 +74,7 @@ func Warn(tag string, description string) {
|
|||||||
func Error(tag string, description string) {
|
func Error(tag string, description string) {
|
||||||
logs.Println("[" + tag + "]" + description)
|
logs.Println("[" + tag + "]" + description)
|
||||||
|
|
||||||
nodeConfig, _ := nodeconfigs.SharedNodeConfig()
|
nodeConfig, _ := configs.SharedAPIConfig()
|
||||||
if nodeConfig == nil {
|
if nodeConfig == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -81,10 +85,28 @@ func Error(tag string, description string) {
|
|||||||
Tag: tag,
|
Tag: tag,
|
||||||
Description: description,
|
Description: description,
|
||||||
Level: "error",
|
Level: "error",
|
||||||
NodeId: nodeConfig.Id,
|
NodeId: nodeConfig.NumberId(),
|
||||||
CreatedAt: time.Now().Unix(),
|
CreatedAt: time.Now().Unix(),
|
||||||
}:
|
}:
|
||||||
default:
|
default:
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 上传日志
|
||||||
|
func uploadLogs() error {
|
||||||
|
Loop:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case log := <-logChan:
|
||||||
|
err := models.SharedNodeLogDAO.CreateLog(models.NodeRoleAPI, log.NodeId, log.Level, log.Tag, log.Description, log.CreatedAt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break Loop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package services
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
rpcutils "github.com/TeaOSLab/EdgeAPI/internal/rpc/utils"
|
||||||
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
"github.com/TeaOSLab/EdgeAPI/internal/utils"
|
||||||
@@ -359,3 +360,61 @@ func (this *UserService) FindUserNodeClusterId(ctx context.Context, req *pb.Find
|
|||||||
}
|
}
|
||||||
return &pb.FindUserNodeClusterIdResponse{NodeClusterId: clusterId}, nil
|
return &pb.FindUserNodeClusterIdResponse{NodeClusterId: clusterId}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置用户能使用的功能
|
||||||
|
func (this *UserService) UpdateUserFeatures(ctx context.Context, req *pb.UpdateUserFeaturesRequest) (*pb.RPCSuccess, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
featuresJSON, err := json.Marshal(req.FeatureCodes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
err = models.SharedUserDAO.UpdateUserFeatures(req.UserId, featuresJSON)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return this.Success()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户所有的功能列表
|
||||||
|
func (this *UserService) FindUserFeatures(ctx context.Context, req *pb.FindUserFeaturesRequest) (*pb.FindUserFeaturesResponse, error) {
|
||||||
|
_, userId, err := this.ValidateAdminAndUser(ctx, 0, req.UserId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if userId > 0 {
|
||||||
|
if userId != req.UserId {
|
||||||
|
return nil, this.PermissionError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
features, err := models.SharedUserDAO.FindUserFeatures(req.UserId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := []*pb.UserFeature{}
|
||||||
|
for _, feature := range features {
|
||||||
|
result = append(result, feature.ToPB())
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.FindUserFeaturesResponse{Features: result}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取所有的功能定义
|
||||||
|
func (this *UserService) FindAllUserFeatureDefinitions(ctx context.Context, req *pb.FindAllUserFeatureDefinitionsRequest) (*pb.FindAllUserFeatureDefinitionsResponse, error) {
|
||||||
|
_, err := this.ValidateAdmin(ctx, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
features := models.FindAllUserFeatures()
|
||||||
|
result := []*pb.UserFeature{}
|
||||||
|
for _, feature := range features {
|
||||||
|
result = append(result, feature.ToPB())
|
||||||
|
}
|
||||||
|
return &pb.FindAllUserFeatureDefinitionsResponse{Features: result}, nil
|
||||||
|
}
|
||||||
|
|||||||
102
internal/rpc/services/service_user_access_key.go
Normal file
102
internal/rpc/services/service_user_access_key.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/TeaOSLab/EdgeAPI/internal/db/models"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 用户AccessKey相关服务
|
||||||
|
type UserAccessKeyService struct {
|
||||||
|
BaseService
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建AccessKey
|
||||||
|
func (this *UserAccessKeyService) CreateUserAccessKey(ctx context.Context, req *pb.CreateUserAccessKeyRequest) (*pb.CreateUserAccessKeyResponse, error) {
|
||||||
|
_, _, err := this.ValidateAdminAndUser(ctx, 0, req.UserId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
userAccessKeyId, err := models.SharedUserAccessKeyDAO.CreateAccessKey(req.UserId, req.Description)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &pb.CreateUserAccessKeyResponse{UserAccessKeyId: userAccessKeyId}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找所有的AccessKey
|
||||||
|
func (this *UserAccessKeyService) FindAllEnabledUserAccessKeys(ctx context.Context, req *pb.FindAllEnabledUserAccessKeysRequest) (*pb.FindAllEnabledUserAccessKeysResponse, error) {
|
||||||
|
_, _, err := this.ValidateAdminAndUser(ctx, 0, req.UserId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
accessKeys, err := models.SharedUserAccessKeyDAO.FindAllEnabledAccessKeys(req.UserId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result := []*pb.UserAccessKey{}
|
||||||
|
for _, accessKey := range accessKeys {
|
||||||
|
result = append(result, &pb.UserAccessKey{
|
||||||
|
Id: int64(accessKey.Id),
|
||||||
|
UserId: int64(accessKey.UserId),
|
||||||
|
SubUserId: int64(accessKey.SubUserId),
|
||||||
|
IsOn: accessKey.IsOn == 1,
|
||||||
|
UniqueId: accessKey.UniqueId,
|
||||||
|
Secret: accessKey.Secret,
|
||||||
|
Description: accessKey.Description,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pb.FindAllEnabledUserAccessKeysResponse{UserAccessKeys: result}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除AccessKey
|
||||||
|
func (this *UserAccessKeyService) DeleteUserAccessKey(ctx context.Context, req *pb.DeleteUserAccessKeyRequest) (*pb.RPCSuccess, error) {
|
||||||
|
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if userId > 0 {
|
||||||
|
ok, err := models.SharedUserAccessKeyDAO.CheckUserAccessKey(userId, req.UserAccessKeyId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return nil, this.PermissionError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.SharedUserAccessKeyDAO.DisableUserAccessKey(req.UserAccessKeyId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return this.Success()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置是否启用AccessKey
|
||||||
|
func (this *UserAccessKeyService) UpdateUserAccessKeyIsOn(ctx context.Context, req *pb.UpdateUserAccessKeyIsOnRequest) (*pb.RPCSuccess, error) {
|
||||||
|
_, userId, err := this.ValidateAdminAndUser(ctx, 0, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if userId > 0 {
|
||||||
|
ok, err := models.SharedUserAccessKeyDAO.CheckUserAccessKey(userId, req.UserAccessKeyId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
return nil, this.PermissionError()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.SharedUserAccessKeyDAO.UpdateAccessKeyIsOn(req.UserAccessKeyId, req.IsOn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return this.Success()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user