mirror of
				https://github.com/TeaOSLab/EdgeAPI.git
				synced 2025-11-04 16:00:24 +08:00 
			
		
		
		
	
		
			
	
	
		
			182 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			182 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package admin
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"context"
							 | 
						||
| 
								 | 
							
									"encoding/base64"
							 | 
						||
| 
								 | 
							
									"encoding/json"
							 | 
						||
| 
								 | 
							
									"errors"
							 | 
						||
| 
								 | 
							
									teaconst "github.com/TeaOSLab/EdgeAPI/internal/const"
							 | 
						||
| 
								 | 
							
									"github.com/TeaOSLab/EdgeAPI/internal/db/models"
							 | 
						||
| 
								 | 
							
									"github.com/TeaOSLab/EdgeAPI/internal/encrypt"
							 | 
						||
| 
								 | 
							
									"github.com/TeaOSLab/EdgeAPI/internal/utils"
							 | 
						||
| 
								 | 
							
									"github.com/iwind/TeaGo/maps"
							 | 
						||
| 
								 | 
							
									"google.golang.org/grpc/metadata"
							 | 
						||
| 
								 | 
							
									"time"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								type Service struct {
							 | 
						||
| 
								 | 
							
									debug bool
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (this *Service) Login(ctx context.Context, req *LoginRequest) (*LoginResponse, error) {
							 | 
						||
| 
								 | 
							
									_, err := this.validateRequest(ctx)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if len(req.Username) == 0 || len(req.Password) == 0 {
							 | 
						||
| 
								 | 
							
										return &LoginResponse{
							 | 
						||
| 
								 | 
							
											AdminId: 0,
							 | 
						||
| 
								 | 
							
											IsOk:    false,
							 | 
						||
| 
								 | 
							
											Message: "请输入正确的用户名密码",
							 | 
						||
| 
								 | 
							
										}, nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									adminId, err := models.SharedAdminDAO.CheckAdminPassword(req.Username, req.Password)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										utils.PrintError(err)
							 | 
						||
| 
								 | 
							
										return nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if adminId <= 0 {
							 | 
						||
| 
								 | 
							
										return &LoginResponse{
							 | 
						||
| 
								 | 
							
											AdminId: 0,
							 | 
						||
| 
								 | 
							
											IsOk:    false,
							 | 
						||
| 
								 | 
							
											Message: "请输入正确的用户名密码",
							 | 
						||
| 
								 | 
							
										}, nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return &LoginResponse{
							 | 
						||
| 
								 | 
							
										AdminId: int64(adminId),
							 | 
						||
| 
								 | 
							
										IsOk:    true,
							 | 
						||
| 
								 | 
							
									}, nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (this *Service) CreateLog(ctx context.Context, req *CreateLogRequest) (*CreateLogResponse, error) {
							 | 
						||
| 
								 | 
							
									adminId, err := this.validateAdminRequest(ctx)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									err = models.SharedLogDAO.CreateAdminLog(adminId, req.Level, req.Description, req.Action, req.Ip)
							 | 
						||
| 
								 | 
							
									return &CreateLogResponse{
							 | 
						||
| 
								 | 
							
										IsOk: err != nil,
							 | 
						||
| 
								 | 
							
									}, err
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (this *Service) CheckAdminExists(ctx context.Context, req *CheckAdminExistsRequest) (*CheckAdminExistsResponse, error) {
							 | 
						||
| 
								 | 
							
									_, err := this.validateRequest(ctx)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if req.AdminId <= 0 {
							 | 
						||
| 
								 | 
							
										return &CheckAdminExistsResponse{
							 | 
						||
| 
								 | 
							
											IsOk: false,
							 | 
						||
| 
								 | 
							
										}, nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ok, err := models.SharedAdminDAO.ExistEnabledAdmin(int(req.AdminId))
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return &CheckAdminExistsResponse{
							 | 
						||
| 
								 | 
							
										IsOk: ok,
							 | 
						||
| 
								 | 
							
									}, nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (this *Service) FindAdminFullname(ctx context.Context, req *FindAdminNameRequest) (*FindAdminNameResponse, error) {
							 | 
						||
| 
								 | 
							
									_, err := this.validateRequest(ctx)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									fullname, err := models.SharedAdminDAO.FindAdminFullname(int(req.AdminId))
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										utils.PrintError(err)
							 | 
						||
| 
								 | 
							
										return nil, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return &FindAdminNameResponse{
							 | 
						||
| 
								 | 
							
										Fullname: fullname,
							 | 
						||
| 
								 | 
							
									}, nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (this *Service) validateRequest(ctx context.Context) (adminId int, err error) {
							 | 
						||
| 
								 | 
							
									var md metadata.MD
							 | 
						||
| 
								 | 
							
									var ok bool
							 | 
						||
| 
								 | 
							
									if this.debug {
							 | 
						||
| 
								 | 
							
										md, ok = metadata.FromOutgoingContext(ctx)
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										md, ok = metadata.FromIncomingContext(ctx)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if !ok {
							 | 
						||
| 
								 | 
							
										return 0, errors.New("context: need 'nodeId'")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									nodeIds := md.Get("nodeid")
							 | 
						||
| 
								 | 
							
									if len(nodeIds) == 0 || len(nodeIds[0]) == 0 {
							 | 
						||
| 
								 | 
							
										return 0, errors.New("context: need 'nodeId'")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									nodeId := nodeIds[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// 获取Node信息
							 | 
						||
| 
								 | 
							
									apiToken, err := models.SharedApiTokenDAO.FindEnabledTokenWithNode(nodeId)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										utils.PrintError(err)
							 | 
						||
| 
								 | 
							
										return 0, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if apiToken == nil {
							 | 
						||
| 
								 | 
							
										return 0, errors.New("can not find token from node id: " + err.Error())
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									tokens := md.Get("token")
							 | 
						||
| 
								 | 
							
									if len(tokens) == 0 || len(tokens[0]) == 0 {
							 | 
						||
| 
								 | 
							
										return 0, errors.New("context: need 'token'")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									token := tokens[0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									data, err := base64.StdEncoding.DecodeString(token)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return 0, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									method, err := encrypt.NewMethodInstance(teaconst.EncryptMethod, apiToken.Secret, nodeId)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										utils.PrintError(err)
							 | 
						||
| 
								 | 
							
										return 0, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									data, err = method.Decrypt(data)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return 0, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if len(data) == 0 {
							 | 
						||
| 
								 | 
							
										return 0, errors.New("invalid token")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									m := maps.Map{}
							 | 
						||
| 
								 | 
							
									err = json.Unmarshal(data, &m)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return 0, errors.New("decode token error: " + err.Error())
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									timestamp := m.GetInt64("timestamp")
							 | 
						||
| 
								 | 
							
									if time.Now().Unix()-timestamp > 600 {
							 | 
						||
| 
								 | 
							
										// 请求超过10分钟认为超时
							 | 
						||
| 
								 | 
							
										return 0, errors.New("authenticate timeout")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									adminId = m.GetInt("adminId")
							 | 
						||
| 
								 | 
							
									return
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (this *Service) validateAdminRequest(ctx context.Context) (adminId int, err error) {
							 | 
						||
| 
								 | 
							
									adminId, err = this.validateRequest(ctx)
							 | 
						||
| 
								 | 
							
									if err != nil {
							 | 
						||
| 
								 | 
							
										return 0, err
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									if adminId <= 0 {
							 | 
						||
| 
								 | 
							
										return 0, errors.New("invalid admin id")
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return
							 | 
						||
| 
								 | 
							
								}
							 |