animeic 1 жил өмнө
parent
commit
cd144600ec

+ 177 - 79
boxcost/api/mac-cpu.go

@@ -1,22 +1,27 @@
 package api
 
 import (
-	"box-cost/conf"
+	"box-cost/db/model"
 	"box-cost/db/repo"
-	"box-cost/log"
-	"crypto/hmac"
+	"crypto"
+	"crypto/rand"
+	"crypto/rsa"
 	"crypto/sha256"
+	"crypto/x509"
+	"encoding/base64"
+	"encoding/json"
+	"encoding/pem"
+	"errors"
 	"fmt"
-	"net/http"
+	"io/ioutil"
+	"os"
 	"time"
 
 	"github.com/gin-gonic/gin"
-	"github.com/shirou/gopsutil/net"
 	"go.mongodb.org/mongo-driver/bson/primitive"
 )
 
 func Mac(r *GinRouter) {
-	r.GET("/mac/info", MacInfo)
 	r.POST("/get/code", GetCode)
 }
 
@@ -29,96 +34,189 @@ type DeviceInfo struct {
 
 const SECRET_KEY = "DFDFEXVEG"
 
-func MacInfo(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	fmt.Println(conf.AppConfig.Name)
-	interfaces, err := net.Interfaces()
+func GetCode(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+
+	form := model.RegCodeReq{}
+	err := c.ShouldBindJSON(&form)
 	if err != nil {
+		fmt.Println(err)
 		return nil, err
 	}
-	macAddr := getRealMacAddr(interfaces)
-	deviceInfo := &DeviceInfo{
-		DeviceId:   UtilMd5(macAddr),
-		AppName:    "Toolchain",
-		AppVersion: "v1.0.0",
-		CreateTime: time.Now(),
+	fmt.Println(form)
+
+	return nil, nil
+
+}
+
+func CreatePrivateKey() error {
+	privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
+	if err != nil {
+		fmt.Println(err)
+		return err
+	}
+	// 将私钥编码为PEM格式
+	privateKeyPEM := pem.EncodeToMemory(&pem.Block{
+		Type:  "RSA PRIVATE KEY",
+		Bytes: x509.MarshalPKCS1PrivateKey(privateKey),
+	})
+	// 将私钥保存到文件中
+	err = ioutil.WriteFile("certs/private_key.pem", privateKeyPEM, 0600)
+	if err != nil {
+		fmt.Println(err)
+		return err
 	}
+	return nil
+}
 
-	return deviceInfo, nil
+func CreatePublicKey(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	// privateKeyFile, err := os.Open(fileName)
+	privateKeyFile, err := os.Open("certs/private_key.pem")
+	if err != nil {
+		fmt.Println(err)
+		return nil, err
+	}
+	defer privateKeyFile.Close()
+	privateKeyPEM, err := ioutil.ReadAll(privateKeyFile)
+	if err != nil {
+		fmt.Println(err)
+		return nil, err
+	}
+	privateKeyBlock, _ := pem.Decode(privateKeyPEM)
+	privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
+	if err != nil {
+		fmt.Println(err)
+		return nil, err
+	}
+	// 根据私钥生成公钥
+	publicKey1 := privateKey.PublicKey
+	// 根据index的 不同生成不同的publickey
+	index, err := repo.RepoCountDoc(apictx.CreateRepoCtx(), "reg-code", repo.Map{"status": 1})
+	if err != nil {
+		fmt.Println(err)
+		return nil, err
+	}
+	publicKey := rsa.PublicKey{
+		N: publicKey1.N,
+		E: 65537 + int(index),
+	}
+	publicKeyPEM := pem.EncodeToMemory(&pem.Block{
+		Type:  "RSA PUBLIC KEY",
+		Bytes: x509.MarshalPKCS1PublicKey(&publicKey),
+	})
+
+	// 将公钥保存到文件中
+	err = ioutil.WriteFile("public_key.pem", publicKeyPEM, 0644)
+	if err != nil {
+		fmt.Println(err)
+		return nil, err
+	}
+	return true, nil
 }
 
-func GetCode(c *gin.Context, apictx *ApiSession) (interface{}, error) {
-	deviceId := c.Query("deviceId")
-	if len(deviceId) < 1 {
-		fmt.Println("deviceId 为空")
-		c.String(http.StatusOK, "err")
-		return nil, nil
-	}
-	key := []byte(SECRET_KEY)
-	message := []byte(deviceId) // 待签名的消息
-
-	// 创建一个 HMAC-SHA256 实例
-	h := hmac.New(sha256.New, key)
-
-	// 写入消息
-	h.Write(message)
-
-	// 计算签名
-	signature := h.Sum(nil)
-	fmt.Printf("%x\n", signature)
-	// fmt.Println(len("86068c837d554c8aba4f997b51be6bc209b68cdad7c5a4a0adccbfc289adf4a2"))
-	// fmt.Println(len("63e208dc7452ab74932b9e37"))
-	// fmt.Println(len(UtilMd5(mac)))
-	appName := c.Query("appName")
-	appVersion := c.Query("appVersion")
-	// create_time := c.Query("createTime")
-
-	// deviceId设置唯一key
-	type RegCode struct {
-		Id         primitive.ObjectID `bson:"_id,omitempty" json:"_id"`
-		AppName    string             `bson:"appName,omitempty" json:"appName"`
-		AppVersion string             `bson:"appVersion,omitempty" json:"appVersion"`
-		DeviceId   string             `bson:"deviceId,omitempty" json:"deviceId"`
-		Key        string             `bson:"key,omitempty" json:"key"`
-		Code       string             `bson:"code,omitempty" json:"code"`
-		CreateTime time.Time          `bson:"createTime,omitempty" json:"createTime"`
-		UpdateTIme time.Time          `bson:"updateTIme,omitempty" json:"updateTIme"`
-		ExpireTime time.Time          `bson:"expireTime,omitempty" json:"expireTime"`
-		Status     int                `bson:"status,omitempty" json:"status"`
-	}
-	_, err := repo.RepoAddDoc(apictx.CreateRepoCtx(), "reg-code", &RegCode{
-
-		AppName:    appName,
-		AppVersion: appVersion,
-		DeviceId:   deviceId,
-		Key:        SECRET_KEY,
-		Code:       fmt.Sprintf("%x", signature),
+// 生成激活码
+func CreateActiveCode(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	// 根据注册码生成激活码
+	// 解析注册码
+	type RegCodeReq struct {
+		Cipher string
+	}
+	form := RegCodeReq{}
+	err := c.ShouldBindJSON(&form)
+	if err != nil {
+		return nil, err
+	}
+	if len(form.Cipher) < 1 {
+		return nil, errors.New("注册码错误")
+	}
+
+	privateFile, err := os.Open("private_key.pem")
+	if err != nil {
+		fmt.Println(err)
+		return false, err
+	}
+	defer privateFile.Close()
+	privateKeyPEM, err := ioutil.ReadAll(privateFile)
+	if err != nil {
+		fmt.Println(err)
+		return false, errors.New("decode err")
+	}
+	privateKeyBlock, _ := pem.Decode(privateKeyPEM)
+	if privateKeyBlock == nil {
+		return false, errors.New("decode err")
+	}
+	privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
+	if err != nil {
+		return false, err
+	}
+
+	decrypted, err := rsa.DecryptOAEP(
+		sha256.New(),
+		rand.Reader,
+		privateKey,
+		[]byte(form.Cipher),
+		[]byte(""),
+	)
+	if err != nil {
+		fmt.Println(err)
+		return false, err
+	}
+
+	decoded, err := base64.StdEncoding.DecodeString(string(decrypted))
+	if err != nil {
+		return nil, err
+	}
+	regCodeReq := model.RegCodeReq{}
+	err = json.Unmarshal(decoded, &regCodeReq)
+	if err != nil {
+		return nil, err
+	}
+	fmt.Println(regCodeReq)
+	// 数据库操作
+	_id, err := repo.RepoAddDoc(apictx.CreateRepoCtx(), "reg-code", &model.RegCode{
+		UserId:     apictx.User.Parent,
+		AppId:      regCodeReq.AppId,
+		AppName:    regCodeReq.AppName,
+		AppVersion: regCodeReq.AppVersion,
+		DeviceId:   regCodeReq.DeviceId,
+		// RegCode:    form.Code,
+		// ActiveCode
+		IsPerm:     regCodeReq.IsPerm,
 		CreateTime: time.Now(),
 		UpdateTIme: time.Now(),
-		ExpireTime: time.Now().AddDate(0, 0, 3),
+		ExpireTime: regCodeReq.ExpireTime,
 		Status:     1,
 	})
+
 	if err != nil {
-		log.Error(err)
 		return nil, err
 	}
 
-	// 输出签名结果
-	c.String(http.StatusOK, fmt.Sprintf("%x", signature))
-	return nil, nil
+	// 组装返回数据
+	id, _ := primitive.ObjectIDFromHex(_id)
 
-}
+	// Calculate hash of ciphertext
+	hash := sha256.Sum256([]byte(form.Cipher))
 
-// b0:6e:bf:c5:32:30
-func getRealMacAddr(netInterfaces []net.InterfaceStat) string {
-	loindex := 0
-	for _, netInterface := range netInterfaces {
-		if netInterface.Name == "lo" {
-			loindex = netInterface.Index
-			break
-		}
+	// Generate signature
+	signature, err := rsa.SignPKCS1v15(
+		rand.Reader,
+		privateKey,
+		crypto.SHA256,
+		hash[:],
+	)
+	if err != nil {
+		fmt.Println(err)
+		return nil, err
 	}
-	if len(netInterfaces) < loindex+1 {
-		return ""
+
+	resp := &model.RegCodeResp{
+		Id:         id,
+		AppId:      regCodeReq.AppId,
+		AppName:    regCodeReq.AppName,
+		AppVersion: regCodeReq.AppVersion,
+		Signature:  string(signature),
+		CipherText: form.Cipher,
 	}
-	return netInterfaces[loindex].HardwareAddr
+
+	return resp, nil
 }

+ 150 - 0
boxcost/api/report.go

@@ -5,9 +5,13 @@ import (
 	"box-cost/db/repo"
 	"errors"
 	"fmt"
+	"strings"
+	"time"
 
 	"github.com/gin-gonic/gin"
+	"github.com/go-redis/redis/v8"
 	"github.com/xuri/excelize/v2"
+	"go.mongodb.org/mongo-driver/bson/primitive"
 )
 
 // 统计报表 按时间范围,供应商  包装-计划(多选) 维度进行过滤,形成报表。可以下载
@@ -20,9 +24,155 @@ func Report(r *GinRouter) {
 	r.GET("/report/produce/download", ReportProduceDownload)
 	r.GET("/report/purchase/download", ReportPurchaseDownload)
 	r.GET("/report/product/download", ReportProductDownload)
+	r.GETJWT("/report/list", ReportList)
 }
 
 // 加工单
+func ReportList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
+	page, size, query := UtilQueryPageSize(c)
+	start, stop := CreatePageRange(page, size)
+	fmt.Println(start, stop)
+
+	filtter := handleReportQuery(query)
+
+	purchases := []*model.PurchaseBill{}
+	produces := []*model.ProduceBill{}
+	products := []*model.ProductBill{}
+
+	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionBillPurchase,
+		Query:       filtter,
+		Project:     []string{"_id", "completeTime"},
+	}, &purchases)
+	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionBillProduce,
+		Query:       filtter,
+		Project:     []string{"_id", "completeTime"},
+	}, &produces)
+	repo.RepoDocsSearch(apictx.CreateRepoCtx(), &repo.PageSearchOptions{
+		CollectName: repo.CollectionBillProduct,
+		Query:       filtter,
+		Project:     []string{"_id", "completeTime"},
+	}, &products)
+
+	// 加入redis有序集合中
+	redisCli := apictx.Svc.Redis
+
+	reportBillKey := "report-bill-list:" + apictx.User.Parent
+
+	isExist := redisCli.Exists(apictx.CreateRepoCtx().Ctx, reportBillKey).Val()
+	// 不存在这个key时
+	if isExist < 1 {
+		if len(purchases) > 0 {
+			for _, purchase := range purchases {
+				member := "purchase_" + purchase.Id.Hex()
+				score := purchase.CompleteTime.Unix()
+				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
+			}
+		}
+		if len(produces) > 0 {
+			for _, produce := range produces {
+				member := "produce_" + produce.Id.Hex()
+				score := produce.CompleteTime.Unix()
+				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
+			}
+		}
+		if len(products) > 0 {
+			for _, product := range products {
+				member := "product_" + product.Id.Hex()
+				score := product.CompleteTime.Unix()
+				redisCli.ZAdd(apictx.CreateRepoCtx().Ctx, reportBillKey, &redis.Z{Score: float64(score), Member: member})
+			}
+		}
+		// 设置过期时间
+		redisCli.Expire(apictx.CreateRepoCtx().Ctx, reportBillKey, 20*time.Second)
+
+	}
+
+	total, err := redisCli.ZCard(apictx.CreateRepoCtx().Ctx, reportBillKey).Uint64()
+	if err != nil {
+		fmt.Println(err)
+		return nil, err
+	}
+
+	reports, err := redisCli.ZRevRange(apictx.CreateRepoCtx().Ctx, reportBillKey, start, stop).Result()
+	if err != nil {
+		return nil, err
+	}
+
+	if len(reports) < 1 {
+		return repo.PageResult{
+			Page:  page,
+			Size:  size,
+			Total: 0,
+		}, nil
+	}
+	lists := []map[string]interface{}{}
+	for _, report := range reports {
+		billArray := strings.Split(report, "_")
+		billType := billArray[0]
+		_billId := billArray[1]
+		billId, _ := primitive.ObjectIDFromHex(_billId)
+		billData := map[string]interface{}{}
+
+		found := false
+		if billType == "purchase" {
+			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+				CollectName: repo.CollectionBillPurchase,
+				Query:       repo.Map{"_id": billId},
+			})
+
+		}
+		if billType == "produce" {
+			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+				CollectName: repo.CollectionBillProduce,
+				Query:       repo.Map{"_id": billId},
+			})
+
+		}
+		if billType == "product" {
+			found, billData = repo.RepoSeachDocMap(apictx.CreateRepoCtx(), &repo.DocSearchOptions{
+				CollectName: repo.CollectionBillProduct,
+				Query:       repo.Map{"_id": billId},
+			})
+
+		}
+		if found {
+			billData["billType"] = billType
+			lists = append(lists, billData)
+		}
+	}
+	return repo.PageResult{
+		List:  lists,
+		Total: int64(total),
+		Page:  page,
+		Size:  size,
+	}, nil
+
+}
+
+func CreatePageRange(page, size int64) (int64, int64) {
+	if page < 1 {
+		page = 1
+	}
+	if size < 1 {
+		size = 10
+	}
+	// var start int64 = 0
+	// var stop int64 = 9
+	// if size < 1 {
+	// 	return start, stop
+	// }
+
+	// if page > 0 {
+	start := (page - 1) * size
+	stop := page*size - 1
+
+	// }
+
+	return start, stop
+}
+
 func ReportProduceList(c *gin.Context, apictx *ApiSession) (interface{}, error) {
 	page, size, query := UtilQueryPageSize(c)
 	// 条件处理

+ 45 - 0
boxcost/db/model/regCode.go

@@ -0,0 +1,45 @@
+package model
+
+import (
+	"time"
+
+	"go.mongodb.org/mongo-driver/bson/primitive"
+)
+
+type RegCodeReq struct {
+	AppId      string    `bson:"appId,omitempty" json:"appId"`
+	AppName    string    `bson:"appName,omitempty" json:"appName"`
+	AppKey     string    `bson:"appKey,omitempty" json:"appKey"`
+	AppVersion string    `bson:"appVersion,omitempty" json:"appVersion"`
+	DeviceId   string    `bson:"deviceId,omitempty" json:"deviceId"`
+	ExpireTime time.Time `bson:"expireTime,omitempty" json:"expireTime"`
+	IsPerm     *bool     `bson:"isPerm,omitempty" json:"isPerm"`
+}
+
+type RegCodeResp struct {
+	Id         primitive.ObjectID `bson:"_id,omitempty" json:"_id"`
+	AppId      string             `bson:"appId,omitempty" json:"appId"`
+	AppName    string             `bson:"appName,omitempty" json:"appName"`
+	AppVersion string             `bson:"appVersion,omitempty" json:"appVersion"`
+	ActiveCode string             `bson:"activeCode,omitempty" json:"activeCode"`
+	CipherText string             `bson:"cipherText,omitempty" json:"cipherText"`
+	Signature  string             `bson:"signature,omitempty" json:"signature"`
+	CreateTime time.Time          `bson:"createTime,omitempty" json:"createTime"`
+}
+
+type RegCode struct {
+	Id         primitive.ObjectID `bson:"_id,omitempty" json:"_id"`
+	UserId     string             `bson:"userId,omitempty" json:"userId"`
+	AppId      string             `bson:"appId,omitempty" json:"appId"`
+	AppName    string             `bson:"appName,omitempty" json:"appName"`
+	AppVersion string             `bson:"appVersion,omitempty" json:"appVersion"`
+	DeviceId   string             `bson:"deviceId,omitempty" json:"deviceId"`
+	Key        string             `bson:"key,omitempty" json:"key"`
+	RegCode    string             `bson:"code,omitempty" json:"code"`
+	ActiveCode string             `bson:"activeCode,omitempty" json:"activeCode"`
+	IsPerm     *bool              `bson:"isPerm,omitempty" json:"isPerm"`
+	CreateTime time.Time          `bson:"createTime,omitempty" json:"createTime"`
+	UpdateTIme time.Time          `bson:"updateTIme,omitempty" json:"updateTIme"`
+	ExpireTime time.Time          `bson:"expireTime,omitempty" json:"expireTime"`
+	Status     int                `bson:"status,omitempty" json:"status"`
+}