caipin 3 年 前
コミット
e82baec234
7 ファイル変更413 行追加86 行削除
  1. 36 0
      dao/project_dao.go
  2. 78 2
      lib/jlzf.go
  3. 143 4
      services/jl_service.go
  4. 88 0
      web/external/jl_ex.go
  5. 6 6
      web/routes/routes.go
  6. 50 1
      web/utils/utils.go
  7. 12 73
      web/viewmodels/jl.go

+ 36 - 0
dao/project_dao.go

@@ -7,6 +7,8 @@
 package dao
 
 import (
+	"errors"
+	"log"
 	"strings"
 
 	"github.com/go-xorm/xorm"
@@ -244,6 +246,40 @@ func (d *ProjectDao) Add(data *models.CmProject) error {
 	return err
 }
 
+// 创建项目和管理员账号
+func (d *ProjectDao) AddProjectAndAccount(projectData *models.CmProject, accountData *models.CmProjectAccount) error {
+	session := d.engine.NewSession()
+	defer session.Close()
+	err := session.Begin()
+	if err != nil {
+		return errors.New("新增项目出错-db")
+	}
+
+	// 1.写入项目表
+	_, err = session.Insert(projectData)
+	if err != nil {
+		log.Println(err)
+		session.Rollback()
+		return errors.New("新增项目出错")
+	}
+
+	// 2.写入账号表
+	_, err = session.Insert(accountData)
+	if err != nil {
+		log.Println(err)
+		session.Rollback()
+		return errors.New("新增账号出错")
+	}
+
+	// 3. 提交事务
+	err = session.Commit()
+	if err != nil {
+		session.Rollback()
+		return errors.New("新增项目出错-db")
+	}
+	return nil
+}
+
 //更新
 func (d *ProjectDao) Update(data *models.CmProject, columns []string) error {
 	//_, err := d.engine.Id(data.Id).MustCols(columns...).Update(data)

+ 78 - 2
lib/jlzf.go

@@ -7,6 +7,14 @@
 package lib
 
 import (
+	"errors"
+	"fmt"
+	"time"
+
+	"github.com/dgrijalva/jwt-go"
+	"github.com/spf13/viper"
+	"go.mod/conf"
+	"go.mod/web/utils"
 	"go.mod/web/viewmodels"
 )
 
@@ -18,10 +26,73 @@ type Jlzf struct {
 
 //创建项目用户service
 func NewJlzf() *Jlzf {
+	// 自动识别开发环境和生产环境
+	debug := getEnvInfo("DEBUG")
+	AuthUrl := ""
+	if debug {
+		AuthUrl = "http://ljr.jl.com:7002"
+	}
+
 	return &Jlzf{
-		AuthUrl: "http://cld.smartcost.com.cn/api/auth",
-		Token:   "sc@ConS!tru@ct*88",
+		AuthUrl: AuthUrl,
+	}
+}
+
+// 生成请求token
+func makeTokenString(claimsData jwt.MapClaims) (string, error) {
+	var (
+		tokenString string
+		err         error
+	)
+	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claimsData)
+	if tokenString, err = token.SignedString([]byte(conf.JLSecretKey)); err != nil {
+		return "", err
+	}
+	return tokenString, nil
+}
+
+// 拉取计量项目信息
+func (j *Jlzf) GetProjectAndAccount(code string, account string) (map[string]interface{}, error) {
+	var (
+		tokenString string
+		err         error
+		resultData  map[string]interface{}
+	)
+	// 1.生成请求数据
+	expirationTime := time.Now().Add(24 * time.Hour)
+	claimsData := jwt.MapClaims{
+		"data": map[string]string{"code": code, "account": account},
+		"exp":  expirationTime.Unix(),
+		// "StandardClaims": jwt.StandardClaims{
+		// 	ExpiresAt: expirationTime.Unix(),
+		// },
+	}
+	// 1-1.生成token
+	if tokenString, err = makeTokenString(claimsData); err != nil {
+		return nil, errors.New("生成请求token错误")
 	}
+	fmt.Println(tokenString)
+	// 1-2.发送请求
+	if resultData, err = utils.PullData("GET", j.AuthUrl+"/management/project", tokenString); err != nil {
+		return nil, errors.New(fmt.Sprintf("计量错误,err= %s", err))
+	}
+
+	fmt.Println(resultData)
+	return resultData, nil
+	// client := &http.Client{}
+	// data := url.Values{}
+	// data.Set("auth", tokenString)
+	// parameter := strings.NewReader(data.Encode())
+	// reqest, err := http.NewRequest("GET", j.AuthUrl, parameter)
+	// if err != nil {
+	// 	return nil, errors.New("计量网络出现问题")
+	// }
+	// reqest.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+	// // 发送请求
+	// response, err := client.Do(reqest)
+}
+func (j *Jlzf) GetAccount() error {
+	return nil
 }
 
 // 验证计量支付项目账号的登陆密码
@@ -47,3 +118,8 @@ func (j *Jlzf) LoginValid(loginData viewmodels.Login) error {
 	//return string(body)
 	return nil
 }
+
+func getEnvInfo(env string) bool {
+	viper.AutomaticEnv()
+	return viper.GetBool(env)
+}

+ 143 - 4
services/jl_service.go

@@ -7,18 +7,31 @@
 package services
 
 import (
+	"errors"
+	"fmt"
+	"net/http"
+	"net/url"
+	"strconv"
+
+	"go.mod/comm"
+	"go.mod/conf"
 	"go.mod/dao"
 	"go.mod/datasource"
+	"go.mod/lib"
+	"go.mod/models"
+	"go.mod/web/viewmodels"
 )
 
 type JlService struct {
-	dao *dao.ProjectDao
+	dao        *dao.ProjectDao
+	accountDao *dao.ProjectAccountDao
 }
 
 // 创建项目用户service
 func NewJlService() *JlService {
 	return &JlService{
-		dao: dao.NewProjectDao(datasource.InstanceDbMaster()),
+		dao:        dao.NewProjectDao(datasource.InstanceDbMaster()),
+		accountDao: dao.NewProjectAccountDao(datasource.InstanceDbMaster()),
 	}
 }
 
@@ -26,8 +39,8 @@ func NewJlService() *JlService {
 func (s *JlService) IsCode(code string) map[string]interface{} {
 	exist := 0
 	if code != "" {
-		projectData := s.dao.GetListByCode(code)
-		if len(projectData) != 0 {
+		projectData := s.dao.GetCode(code)
+		if projectData.Id != 0 {
 			exist = 1
 		}
 	}
@@ -38,3 +51,129 @@ func (s *JlService) IsCode(code string) map[string]interface{} {
 
 	return data
 }
+
+// 从计量来的项目和管理员账号,添加入项目管理
+func (s *JlService) ProjectAdd(claimsData *viewmodels.Jl) (map[string]interface{}, error) {
+
+	var (
+		err          error
+		JlResultData map[string]interface{}
+		accountData  *models.CmProjectAccount
+	)
+
+	Jlzf := lib.NewJlzf()
+	// 1.获得计量 账号和项目 信息
+	if JlResultData, err = Jlzf.GetProjectAndAccount(claimsData.Code, claimsData.Account); err != nil {
+		return nil, err
+	}
+	fmt.Println(JlResultData)
+
+	// 2.获得本地项目
+	projectData := s.dao.GetCode(claimsData.Code)
+	// 项目不存在
+	if projectData.Id == 0 {
+		// 2-1. 创建项目和账号 TODO
+		project := &models.CmProject{}
+
+		account := &models.CmProjectAccount{}
+		if err = s.dao.AddProjectAndAccount(project, account); err != nil {
+			return nil, err
+		}
+		// 	project := &models.CmProject{}
+		// project.Name = projectVM.Name
+		// project.Code = projectVM.Code
+		// project.CategoryId = projectVM.CategoryId
+		// project.Category = projectVM.Category
+		// project.InsideCategoryid = projectVM.InsideCategoryid
+		// project.InsideCategory = projectVM.InsideCategory
+		// project.StaffId = projectVM.StaffId
+		// project.StaffName = projectVM.StaffName
+		// project.CreateTime = time.Now()
+		// project.CreateName = projectVM.CreateName
+		// project.CreateCategory = projectVM.CreateCategory
+		// project.Remark = projectVM.Remark
+
+	} else {
+		// 2-2. 是否有该账号
+		accountData = s.accountDao.GetAccountProjectId(claimsData.Account, projectData.Id)
+		// 2-2-1 账号不存在
+		if accountData.Id == 0 {
+			// 2-2-2. 创建 账号 TODO
+			account := &models.CmProjectAccount{}
+			if err = s.accountDao.Add(account); err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	data := map[string]interface{}{
+		"sync": 1,
+	}
+	return data, nil
+}
+
+func (s *JlService) AuthLogin(claimsData *viewmodels.Jl, writer http.ResponseWriter) (*viewmodels.ProjectAccount, error) {
+	// 1-1.工程项目是否存在
+	projectInfo := s.dao.GetCode(claimsData.Code)
+
+	if projectInfo.Id == 0 {
+		return nil, errors.New("工程建设管理员还未创建项目,禁止登录")
+	}
+	// 1-2.获得项目管理员
+	projectAdminInfo := s.accountDao.Get(projectInfo.UserId, projectInfo.Id)
+	if projectAdminInfo.Id == 0 {
+		return nil, errors.New("工程建设管理员不存在,禁止登录")
+	}
+
+	// 2.验证登陆-临时
+	projectAccountInfo := s.accountDao.GetAccountProjectId(claimsData.Account, projectInfo.Id)
+	// 未账号改账号
+	if projectAccountInfo.Id == 0 {
+		// 到计量拉取普通账号 - TODO
+		// Jlzf := lib.NewJlzf()
+		// // 1.获得计量 账号和项目 信息
+		// if JlResultData, err := Jlzf.GetProjectAndAccount(claimsData.Code, claimsData.Account); err != nil {
+		// 	return nil, err
+		// }
+		// // 2-. 创建 账号 TODO
+		// account := &models.CmProjectAccount{}
+		// if err := s.accountDao.Add(account); err != nil {
+		// 	return nil, err
+		// }
+	}
+	// 2-1.账号停用
+	if projectAccountInfo.Enable == 0 {
+		return nil, errors.New("该账号已被停用")
+	}
+
+	// 加密用户标识
+	identity, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.Id), conf.CookieSecret)
+	if err != nil {
+		return nil, err
+	}
+	// 加密项目标识
+	projectId, err := comm.AesEncrypt(strconv.Itoa(projectAccountInfo.ProjectId), conf.CookieSecret)
+	if err != nil {
+		return nil, err
+	}
+
+	digitalToken := comm.CreateSign(conf.CookieSecret + strconv.Itoa(projectAccountInfo.Id))
+
+	// 设置cookie
+	maxAge := 60 * 60 * 24 * 7
+	params := url.Values{}
+	params.Add("identity", identity)
+	params.Add("attachedIdentity", projectId)
+	params.Add("digitalToken", digitalToken)
+	c := &http.Cookie{
+		Name:     "cm",
+		Value:    params.Encode(),
+		Path:     "/",
+		MaxAge:   maxAge,
+		HttpOnly: true,
+	}
+	http.SetCookie(writer, c)
+
+	viewAccountData := comm.MakeProjectAccountVM(projectAccountInfo)
+	return &viewAccountData, nil
+}

+ 88 - 0
web/external/jl_ex.go

@@ -61,3 +61,91 @@ func (c *JlEx) PostCalibration() {
 		"data": result,
 	})
 }
+
+// 添加项目和账号
+func (c *JlEx) PostProjectAdd() {
+	// 1.获得数据
+	data := &viewmodels.Jl{}
+	if err := c.Ctx.ReadForm(data); err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 1-1.校验是否存在TOKEN
+	if err := data.ValidateToken(); err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 1-2.验证jwt
+	claims, err := utils.ValidateJwt(data.Token)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+
+	// 1-3.验证参数的正确性
+	claimsData := &viewmodels.Jl{
+		Code:    fmt.Sprintf("%s", claims["code"]),
+		Account: fmt.Sprintf("%s", claims["account"]),
+	}
+	if err := claimsData.ValidateProjectAdd(); err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+
+	JlService := services.NewJlService()
+	result, err := JlService.ProjectAdd(claimsData)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	c.Ctx.JSON(iris.Map{
+		"code": 0,
+		"msg":  "",
+		"data": result,
+	})
+}
+
+// 授权登陆
+func (c *JlEx) PostAuthLogin() {
+	// 1.获得数据
+	data := &viewmodels.Jl{}
+	if err := c.Ctx.ReadForm(data); err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 1-1.校验是否存在TOKEN
+	if err := data.ValidateToken(); err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 1-2.验证jwt
+	claims, err := utils.ValidateJwt(data.Token)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+
+	// 1-3.验证参数的正确性
+	claimsData := &viewmodels.Jl{
+		Code:    fmt.Sprintf("%s", claims["code"]),
+		Account: fmt.Sprintf("%s", claims["account"]),
+	}
+	if err := claimsData.ValidateProjectAdd(); err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+
+	JlService := services.NewJlService()
+	result, err := JlService.AuthLogin(claimsData, c.Ctx.ResponseWriter())
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	c.Ctx.JSON(iris.Map{
+		"code": 0,
+		"msg":  "",
+		"data": result,
+	})
+}
+
+//

+ 6 - 6
web/routes/routes.go

@@ -221,18 +221,18 @@ func Configure(b *bootstrap.Bootstrapper) {
 	jlEx.Handle(new(external.JlEx))
 
 	// 后台相关
-	backstageCM := mvc.New(b.Party("/api/backstage/login", protect))
+	backstageCM := mvc.New(b.Party("/api/backstage/login"))
 	backstageCM.Register(backstageService)
 	backstageCM.Handle(new(backstage.LoginBs))
 
-	backstageProjectCM := mvc.New(b.Party("/api/backstage/project", protect))
+	backstageProjectCM := mvc.New(b.Party("/api/backstage/project"))
 	backstageProjectCM.Register(ProjectService)
 	backstageProjectCM.Register(backstageService)
 	backstageProjectCM.Router.Use(middleware.SessionsBackstageAuth)
 	backstageProjectCM.Router.Use(middleware.AccessBackstageAuth)
 	backstageProjectCM.Handle(new(backstage.ProjectBs))
 
-	backstageAccountCM := mvc.New(b.Party("/api/backstage/account", protect))
+	backstageAccountCM := mvc.New(b.Party("/api/backstage/account"))
 	backstageAccountCM.Register(ProjectAccountService)
 	backstageAccountCM.Register(ProjectService)
 	backstageAccountCM.Register(BidAccountService)
@@ -241,17 +241,17 @@ func Configure(b *bootstrap.Bootstrapper) {
 	backstageAccountCM.Router.Use(middleware.AccessBackstageAuth)
 	backstageAccountCM.Handle(new(backstage.ProjectAccountBs))
 
-	managerCM := mvc.New(b.Party("/api/backstage/manager", protect))
+	managerCM := mvc.New(b.Party("/api/backstage/manager"))
 	managerCM.Register(managerService)
 	managerCM.Router.Use(middleware.SessionsBackstageAuth)
 	managerCM.Handle(new(backstage.ManagerBs))
 
-	groupCM := mvc.New(b.Party("/api/backstage/group", protect))
+	groupCM := mvc.New(b.Party("/api/backstage/group"))
 	groupCM.Register(groupService)
 	groupCM.Router.Use(middleware.SessionsBackstageAuth)
 	groupCM.Handle(new(backstage.GroupBs))
 
-	versionCM := mvc.New(b.Party("/api/backstage/version", protect))
+	versionCM := mvc.New(b.Party("/api/backstage/version"))
 	versionCM.Register(versionService)
 	versionCM.Router.Use(middleware.SessionsBackstageAuth)
 	versionCM.Handle(new(backstage.VersionBs))

+ 50 - 1
web/utils/utils.go

@@ -7,9 +7,13 @@
 package utils
 
 import (
+	"encoding/json"
 	"errors"
 	"fmt"
+	"io/ioutil"
 	"log"
+	"net/http"
+	"net/url"
 	"strconv"
 	"strings"
 	"time"
@@ -142,7 +146,7 @@ func ValidateJwt(tokenStr string) (jwt.MapClaims, error) {
 	expirationTime := time.Now().Add(5 * time.Minute)
 	token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
 		"code":    "gs01",
-		"isAdmin": 1,
+		"account": "蓝健荣",
 		"StandardClaims": jwt.StandardClaims{
 			ExpiresAt: expirationTime.Unix(),
 		},
@@ -172,6 +176,51 @@ func ValidateJwt(tokenStr string) (jwt.MapClaims, error) {
 	return claims, nil
 }
 
+func PullData(method string, authUrl string, tokenString string) (map[string]interface{}, error) {
+
+	// 1.构建请求体
+	client := &http.Client{}
+	data := url.Values{}
+	data.Set("auth", tokenString)
+	parameter := strings.NewReader(data.Encode())
+
+	// 2.开始请求准备
+	reqest, err := http.NewRequest(method, authUrl, parameter)
+	if err != nil {
+		log.Println("请求移除, error=", err)
+		return nil, errors.New("网络出现问题")
+	}
+	if method == "POST" || method == "post" {
+		reqest.Header.Add("Content-Type", "application/x-www-form-urlencoded")
+	}
+	fmt.Println(reqest)
+	// 3.发送请求
+	response, err := client.Do(reqest)
+	if err != nil {
+		log.Println("请求移除, error=", err)
+		return nil, errors.New("网络出现问题")
+	}
+	if response.StatusCode != 200 {
+		return nil, errors.New("请求发送错误")
+	}
+
+	// 4.结构化返回数据
+	body, _ := ioutil.ReadAll(response.Body)
+	// fmt.Println(string(body))
+	result := map[string]interface{}{}
+	err = json.Unmarshal(body, &result)
+	if err != nil {
+		log.Println("请求移除, error=", err)
+		return nil, errors.New("解析数据错误")
+	}
+
+	if result["code"] != 0 {
+		return nil, errors.New(fmt.Sprintf("%s", result["msg"]))
+	}
+
+	return result, nil
+}
+
 // // 获得项目ID
 // func GetProjectId(ctx iris.Context) (int, error) {
 // 	jwtInfo := ctx.Values().Get("jwt").(*jwt.Token)

+ 12 - 73
web/viewmodels/jl.go

@@ -14,8 +14,9 @@ import (
 )
 
 type Jl struct {
-	Token string `form:"token" json:"token" `
-	Code  string `form:"code" json:"code" `
+	Token   string `form:"token" json:"token" `
+	Code    string `form:"code" json:"code" `
+	Account string `form:"account" json:"account" `
 }
 
 // 校验项目接口
@@ -25,79 +26,17 @@ func (l Jl) ValidateToken() error {
 	)
 }
 
-// 验证传参
+// 验证检验项目
 func (l Jl) ValidateParameter() error {
 	return validation.ValidateStruct(&l,
-		validation.Field(&l.Code, validation.Required.Error("token不能为空")),
+		validation.Field(&l.Code, validation.Required.Error("项目编号不能为空")),
 	)
 }
 
-// // 校验jwt
-// func (l Jl) ValidateJwt(tokenStr string, ctx iris.Context) (jwt.MapClaims, error) {
-
-// 	// 验证
-// 	// j := jwtmiddleware.New(jwtmiddleware.Config{
-// 	// 	// 返回一个密匙
-// 	// 	ValidationKeyGetter: func(token *jwt.Token) (i interface{}, e error) {
-// 	// 		return conf.JLSecretKey, nil
-// 	// 	},
-// 	// 	Extractor: jwtmiddleware.FromParameter("token"),
-
-// 	// 	SigningMethod: jwtmiddleware.SigningMethodHS256,
-// 	// })
-
-// 	// if err := j.CheckJWT(ctx); err != nil {
-// 	// 	fmt.Println(err)
-// 	// }
-
-// 	// 解析
-// 	// tokenClaims, err := jwt.ParseWithClaims(tokenStr, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) {
-// 	// 	return []byte(conf.JLSecretKey), nil
-// 	// })
-// 	// if err != nil {
-// 	// 	return nil, err
-// 	// }
-
-// 	// 初始化`Claims`实例
-// 	// claims := &Claims{}
-// 	// 解析JWT字符串并将结果存储在`claims`中。
-// 	// 请注意,我们也在此方法中传递了密钥。
-// 	// 如果令牌无效(如果令牌已根据我们设置的登录到期时间过期)或者签名不匹配,此方法会返回错误.
-// 	// tkn, err := jwt.ParseWithClaims(tokenStr, claims, func(token *jwt.Token) (interface{}, error) {
-// 	// 	return []byte(conf.JLSecretKey), nil
-// 	// })
-
-// 	// 在这里声明令牌的到期时间,我们将其保留为5分钟
-// 	expirationTime := time.Now().Add(5 * time.Minute)
-
-// 	claims := &Claims{
-// 		Username: "蔡频",
-// 		StandardClaims: jwt.StandardClaims{
-// 			// In JWT, the expiry time is expressed as unix milliseconds
-// 			ExpiresAt: expirationTime.Unix(),
-// 		},
-// 	}
-
-// 	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
-// 	// 创建JWT字符串
-// 	tokenString, err := token.SignedString([]byte(conf.JLSecretKey))
-
-// 	fmt.Println(tokenString)
-// 	fmt.Println("tokenString")
-
-// 	parseAuth, err := jwt.Parse(tokenStr, func(*jwt.Token) (interface{}, error) {
-// 		return []byte(conf.JLSecretKey), nil
-// 	})
-// 	if err != nil {
-// 		log.Println("JWT异常, error=", err)
-// 		return nil, err
-// 	}
-// 	if !parseAuth.Valid {
-// 		return nil, errors.New("无效签名")
-// 	}
-// 	// claims := parseAuth.Claims.(jwt.MapClaims)
-
-// 	fmt.Println(claims)
-
-// 	return nil, nil
-// }
+// 添加项目和账号验证
+func (l Jl) ValidateProjectAdd() error {
+	return validation.ValidateStruct(&l,
+		validation.Field(&l.Code, validation.Required.Error("项目编号不能为空")),
+		validation.Field(&l.Account, validation.Required.Error("账号不能为空")),
+	)
+}