Kaynağa Gözat

完成utm鉴权相关接口

yjp 3 hafta önce
ebeveyn
işleme
9882d49d9a

+ 1 - 3
README.md

@@ -6,6 +6,4 @@ gateway/gw: 网关,默认端口10000
 
 gateway/sagagw: saga网关,默认端口10001
 
-um: 简化版用户管理服务,默认端口10002
-
-tm:简化版租户管理服务,默认端口10003
+utm: 简化版用户管理服务,默认端口10002

+ 6 - 1
gateway/gw/api/api.go

@@ -1,6 +1,8 @@
 package api
 
 import (
+	"baize_scaffold/gateway/gw/api/root"
+	v1 "baize_scaffold/gateway/gw/api/v1"
 	"baize_scaffold/gateway/gw/config"
 
 	"git.sxidc.com/go-framework/baize"
@@ -16,10 +18,13 @@ func NewGateway() {
 		return
 	}
 
-	appInstance = baize.NewApplication(config.GetSagaGatewayConfig().ApplicationConfig)
+	appInstance = baize.NewApplication(config.GetGatewayConfig().ApplicationConfig)
 
 	// 创建gateway
 	gatewayInstance = gateway.NewGateway(appInstance.Api())
+
+	root.Init(gatewayInstance)
+	v1.Init(gatewayInstance)
 }
 
 func DestroyGateway() {

+ 19 - 0
gateway/gw/api/root/auth/auth.go

@@ -0,0 +1,19 @@
+package auth
+
+import (
+	"baize_scaffold/gateway/gw/config"
+
+	"git.sxidc.com/go-framework/baize/convenient/gwtools/pass_through"
+	"git.sxidc.com/go-framework/baize/framework/gateway"
+)
+
+var (
+	umUrl = config.GetGatewayConfig().ServicesConfig.UMBaseUrl + "/utm/api"
+)
+
+func Init(builder *gateway.Builder) {
+	pass_through.PostRoute(builder, &pass_through.Simple{
+		RelativePath: "/login",
+		ServiceUrl:   umUrl + "/login",
+	})
+}

+ 17 - 0
gateway/gw/api/root/root.go

@@ -0,0 +1,17 @@
+package root
+
+import (
+	"baize_scaffold/gateway/gw/api/v1/auth"
+
+	"git.sxidc.com/go-framework/baize/framework/core/api"
+	"git.sxidc.com/go-framework/baize/framework/gateway"
+)
+
+var (
+	builder *gateway.Builder
+)
+
+func Init(gw *gateway.Gateway) {
+	builder = gw.NewBuilder(api.RouterPrefix, "")
+	auth.Init(builder)
+}

+ 15 - 0
gateway/gw/api/v1/auth/auth.go

@@ -0,0 +1,15 @@
+package auth
+
+import (
+	"baize_scaffold/gateway/gw/config"
+
+	"git.sxidc.com/go-framework/baize/framework/gateway"
+)
+
+var (
+	umUrl = config.GetGatewayConfig().ServicesConfig.UMBaseUrl + "/utm/api/v1"
+)
+
+func Init(builder *gateway.Builder) {
+
+}

+ 18 - 0
gateway/gw/api/v1/v1.go

@@ -0,0 +1,18 @@
+package v1
+
+import (
+	"baize_scaffold/gateway/gw/api/v1/auth"
+	"baize_scaffold/gateway/middleware"
+
+	"git.sxidc.com/go-framework/baize/framework/core/api"
+	"git.sxidc.com/go-framework/baize/framework/gateway"
+)
+
+var (
+	v1Builder *gateway.Builder
+)
+
+func Init(gw *gateway.Gateway) {
+	v1Builder = gw.NewBuilder(api.RouterPrefix, "v1", middleware.Authentication())
+	auth.Init(v1Builder)
+}

+ 3 - 3
gateway/gw/config/config.go

@@ -14,12 +14,12 @@ type servicesConfig struct {
 	TMBaseUrl  string `yaml:"tm_base_url"`
 }
 
-type SagaGatewayConfig struct {
+type GatewayConfig struct {
 	ApplicationConfig application.Config
 	ServicesConfig    servicesConfig `yaml:"services"`
 }
 
-var conf = &SagaGatewayConfig{}
+var conf = &GatewayConfig{}
 
 func init() {
 	configFilePath := os.Getenv("CONFIG_FILE_PATH")
@@ -43,6 +43,6 @@ func init() {
 	fmt.Println("Load config file finish")
 }
 
-func GetSagaGatewayConfig() *SagaGatewayConfig {
+func GetGatewayConfig() *GatewayConfig {
 	return conf
 }

+ 143 - 0
gateway/middleware/auth.go

@@ -0,0 +1,143 @@
+package middleware
+
+import (
+	"baize_scaffold/gateway/gw/config"
+	"fmt"
+	"net/http"
+
+	"github.com/pkg/errors"
+
+	"git.sxidc.com/go-framework/baize/framework/core/api/response"
+	"git.sxidc.com/go-framework/baize/framework/gateway"
+	"git.sxidc.com/service-supports/fslog"
+	"github.com/dgrijalva/jwt-go/request"
+)
+
+func Authentication() gateway.Handler {
+	return func(requestBuilder *gateway.RequestBuilder) {
+		c := requestBuilder.ApiContext()
+		respFunc := response.SendMapResponse
+
+		token, err := request.AuthorizationHeaderExtractor.ExtractToken(c.Request)
+		if err != nil {
+			fslog.Error(err)
+			respFunc(c, http.StatusUnauthorized, map[string]any{
+				"accessToken": "",
+			}, errors.New("token错误"))
+			c.Abort()
+			return
+		}
+
+		requestBuilder.Post(&gateway.PostRequest{
+			Url: config.GetGatewayConfig().ServicesConfig.UMBaseUrl + "/utm/api/v1/checkToken",
+			Body: map[string]any{
+				"token": token,
+			},
+		}).ResponseSuccessCallback(func(c *gateway.RequestBuilderContext) {
+			userID, ok := c.GetResultMapValue("userId").(string)
+			if !ok {
+				fslog.Error(err)
+				respFunc(c.ApiContext(), http.StatusUnauthorized, map[string]any{
+					"accessToken": "",
+				}, errors.New("用户ID获取错误"))
+				c.ApiContext().Abort()
+			}
+		}).Request()
+
+		currentTenant, err := ngumInner.GetUserCurrentTenant(umCheckResult.UserID)
+		if err != nil {
+			fslog.Error(err)
+			respFunc(c, http.StatusUnauthorized, map[string]any{
+				"code":        ErrGetCurOrg.Code(),
+				"accessToken": "",
+			}, ErrGetCurOrg)
+			c.Abort()
+			return
+		}
+
+		tangentSimpleUserInfo := new(mbum_resp.TangentUserProfileInfo)
+		tenantStatus := new(ngtm_resp.TenantStatus)
+		if currentTenant.ID != "" {
+			tenantStatus, err = ngtmInner.GetTenantStatus(currentTenant.ID)
+			if err != nil {
+				fslog.Error(err)
+				respFunc(c, http.StatusUnauthorized, map[string]any{
+					"code":        ErrGetCurOrg.Code(),
+					"accessToken": "",
+				}, ErrGetCurOrgUserInfo)
+				c.Abort()
+				return
+			}
+
+			tangentSimpleUserInfo, err = ngumInner.GetTenantUserProfileSimpleByID(currentTenant.ID, umCheckResult.UserID)
+			if err != nil {
+				fslog.Error(err)
+				respFunc(c, http.StatusUnauthorized, map[string]any{
+					"code":        ErrGetCurOrg.Code(),
+					"accessToken": "",
+				}, ErrGetCurOrgUserInfo)
+				c.Abort()
+				return
+			}
+		}
+
+		// 2.使用新的uas 直接根据用户id和访问资源信息判断是否有权限。
+		authInfo, err := uasV1.Authentication(&uasV1Req.AuthenticationJsonBody{
+			TenantID:       currentTenant.ID,
+			UserID:         umCheckResult.UserID,
+			Namespace:      global.Namespace,
+			Resource:       c.FullPath(),
+			Action:         c.Request.Method,
+			IsExpireStatus: tenantStatus.IsExpireStatus,
+		})
+		if err != nil {
+			fslog.Error(err)
+			respFunc(c, http.StatusUnauthorized, map[string]any{
+				"code":        ErrAuth.Code(),
+				"accessToken": "",
+			}, ErrAuth)
+			c.Abort()
+			return
+		}
+
+		if authInfo != nil && !authInfo.Pass {
+			fslog.Error(fmt.Errorf("path:%s,method:%s", c.Request.URL.Path, c.Request.Method))
+			respFunc(c, http.StatusUnauthorized, map[string]any{
+				"code":        ErrNoPermission.Code(),
+				"accessToken": "",
+			}, ErrNoPermission)
+			c.Abort()
+			return
+		}
+
+		// 组合角色
+		roles := make([]RoleInfo, 0)
+		for _, sysRole := range authInfo.SysRoles {
+			roles = append(roles, RoleInfo{
+				ID:   sysRole.ID,
+				Name: sysRole.Name,
+			})
+
+		}
+		for _, tangentRole := range authInfo.TenantRoles {
+			roles = append(roles, RoleInfo{
+				ID:   tangentRole.ID,
+				Name: tangentRole.Name,
+			})
+		}
+
+		c.SetUserInfo(&UserInfoWithRoles{
+			ID:                 umCheckResult.UserID,
+			UserName:           umCheckResult.UserName,
+			Updated:            umCheckResult.Updated,
+			ProfileName:        tangentSimpleUserInfo.Name,
+			OrgInfo:            currentTenant,
+			RoleInfos:          roles,
+			TangentUserProfile: tangentSimpleUserInfo,
+		})
+
+		c.SetTenantInfo(currentTenant)
+
+		c.Next()
+	}
+}

+ 4 - 11
go.mod

@@ -6,10 +6,9 @@ require (
 	git.sxidc.com/go-framework/baize v1.7.4
 	git.sxidc.com/go-tools/utils v1.5.33
 	git.sxidc.com/service-supports/fslog v0.5.9
-	github.com/fatih/structs v1.1.0
-	github.com/gin-gonic/gin v1.10.0
+	github.com/dgrijalva/jwt-go v3.2.0+incompatible
+	github.com/pkg/errors v0.9.1
 	github.com/vrecan/death v3.0.1+incompatible
-	github.com/xuri/excelize/v2 v2.8.1
 	gopkg.in/yaml.v3 v3.0.1
 )
 
@@ -18,7 +17,6 @@ require (
 	github.com/Masterminds/goutils v1.1.1 // indirect
 	github.com/Masterminds/semver/v3 v3.2.0 // indirect
 	github.com/Masterminds/sprig/v3 v3.2.3 // indirect
-	github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible // indirect
 	github.com/bytedance/sonic v1.11.6 // indirect
 	github.com/bytedance/sonic/loader v0.1.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
@@ -28,8 +26,10 @@ require (
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/eclipse/paho.mqtt.golang v1.4.3 // indirect
 	github.com/fatih/color v1.7.0 // indirect
+	github.com/fatih/structs v1.1.0 // indirect
 	github.com/gabriel-vasile/mimetype v1.4.3 // indirect
 	github.com/gin-contrib/sse v0.1.0 // indirect
+	github.com/gin-gonic/gin v1.10.0 // indirect
 	github.com/git-chglog/git-chglog v0.0.0-20190611050339-63a4e637021f // indirect
 	github.com/go-playground/locales v0.14.1 // indirect
 	github.com/go-playground/universal-translator v0.18.1 // indirect
@@ -61,13 +61,9 @@ require (
 	github.com/mitchellh/reflectwalk v1.0.0 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
-	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
 	github.com/mwitkow/go-proto-validators v0.3.2 // indirect
 	github.com/pelletier/go-toml/v2 v2.2.2 // indirect
-	github.com/pkg/errors v0.9.1 // indirect
 	github.com/redis/go-redis/v9 v9.4.0 // indirect
-	github.com/richardlehane/mscfb v1.0.4 // indirect
-	github.com/richardlehane/msoleps v1.0.3 // indirect
 	github.com/robinjoseph08/redisqueue/v2 v2.1.0 // indirect
 	github.com/satori/go.uuid v1.2.0 // indirect
 	github.com/shopspring/decimal v1.2.0 // indirect
@@ -77,8 +73,6 @@ require (
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	github.com/ugorji/go/codec v1.2.12 // indirect
 	github.com/urfave/cli v1.20.0 // indirect
-	github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
-	github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
 	go.uber.org/multierr v1.11.0 // indirect
 	go.uber.org/zap v1.27.0 // indirect
 	golang.org/x/arch v0.8.0 // indirect
@@ -87,7 +81,6 @@ require (
 	golang.org/x/sync v0.6.0 // indirect
 	golang.org/x/sys v0.20.0 // indirect
 	golang.org/x/text v0.15.0 // indirect
-	golang.org/x/time v0.3.0 // indirect
 	golang.org/x/tools v0.7.0 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
 	google.golang.org/grpc v1.64.0 // indirect

+ 2 - 17
go.sum

@@ -14,8 +14,6 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj
 github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
 github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw=
 github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc=
-github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g=
-github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
 github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
 github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
 github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
@@ -35,6 +33,8 @@ github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQ
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
 github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
 github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik=
@@ -149,8 +149,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
-github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
-github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 github.com/mwitkow/go-proto-validators v0.3.2 h1:qRlmpTzm2pstMKKzTdvwPCF5QfBNURSlAgN/R+qbKos=
 github.com/mwitkow/go-proto-validators v0.3.2/go.mod h1:ej0Qp0qMgHN/KtDyUt+Q1/tA7a5VarXUOUxD+oeD30w=
 github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@@ -168,11 +166,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk=
 github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
-github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
-github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
-github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
-github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
-github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 github.com/robinjoseph08/redisqueue/v2 v2.1.0 h1:GactHlrxS8YSCJc4CbP1KbTObo14pieNmNWSUlquTGI=
 github.com/robinjoseph08/redisqueue/v2 v2.1.0/go.mod h1:fiNYBqIF/DqZxKvO6faLB6nkBtfJucuM+rDbFhZG1vs=
 github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
@@ -212,12 +205,6 @@ github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
 github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 github.com/vrecan/death v3.0.1+incompatible h1:hYRRqrdyoUAbymk2KJ8tNHmZFKcVeThRUySCqwC5Itg=
 github.com/vrecan/death v3.0.1+incompatible/go.mod h1:ektTae4lwvcXJ7pytrLb2N0w7mwhzmu+f5vRHYzy33E=
-github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0=
-github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
-github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ=
-github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE=
-github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4=
-github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
@@ -239,8 +226,6 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4
 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
 golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
 golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
-golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
-golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=

+ 0 - 14
tm/application/service/service.go

@@ -1,14 +0,0 @@
-package service
-
-import "git.sxidc.com/go-framework/baize/framework/core/application"
-
-const (
-	dbSchema = "test"
-)
-
-type Service interface {
-	Init(appInstance *application.App) error
-	Destroy() error
-}
-
-var RegisteredServices = []Service{}

+ 0 - 3
tm/deployment/config/config.yaml

@@ -1,3 +0,0 @@
-api:
-  url_prefix: /tm/api
-  port: 10003

+ 0 - 30
tm/main.go

@@ -1,30 +0,0 @@
-package main
-
-import (
-	"baize_scaffold/tm/application"
-	"syscall"
-
-	DEATH "github.com/vrecan/death"
-)
-
-func main() {
-	application.NewApp()
-	defer application.DestroyApp()
-
-	go func() {
-		err := application.Start()
-		if err != nil {
-			panic(err)
-		}
-	}()
-
-	defer func() {
-		err := application.Finish()
-		if err != nil {
-			panic(err)
-		}
-	}()
-
-	death := DEATH.NewDeath(syscall.SIGINT, syscall.SIGTERM)
-	_ = death.WaitForDeath()
-}

+ 0 - 65
um/application/application.go

@@ -1,65 +0,0 @@
-package application
-
-import (
-	"baize_scaffold/um/application/service"
-	"baize_scaffold/um/config"
-
-	"git.sxidc.com/go-framework/baize"
-	"git.sxidc.com/go-framework/baize/framework/core/application"
-)
-
-var appInstance *application.App
-
-func NewApp() {
-	if appInstance != nil {
-		return
-	}
-
-	appInstance = baize.NewApplication(config.GetConfig().ApplicationConfig)
-
-	// 注册Router
-	appInstance.Api().PrefixRouter().RegisterVersionedRouter("v1")
-}
-
-func DestroyApp() {
-	if appInstance == nil {
-		return
-	}
-
-	baize.DestroyApplication(appInstance)
-	appInstance = nil
-}
-
-func Start() error {
-	// 初始化服务
-	for _, svc := range service.RegisteredServices {
-		err := svc.Init(appInstance)
-		if err != nil {
-			return err
-		}
-	}
-
-	err := appInstance.Start()
-	if err != nil {
-		return err
-	}
-
-	return nil
-}
-
-func Finish() error {
-	err := appInstance.Finish()
-	if err != nil {
-		return err
-	}
-
-	// 销毁服务
-	for _, svc := range service.RegisteredServices {
-		err := svc.Destroy()
-		if err != nil {
-			return err
-		}
-	}
-
-	return nil
-}

+ 0 - 30
um/config/config.go

@@ -1,30 +0,0 @@
-package config
-
-import (
-	"fmt"
-	"os"
-
-	"git.sxidc.com/go-framework/baize/framework/core/application"
-)
-
-type Config struct {
-	ApplicationConfig application.Config
-}
-
-var conf Config
-
-func init() {
-	configFilePath := os.Getenv("CONFIG_FILE_PATH")
-	applicationConfig, err := application.LoadFromYamlFile(configFilePath)
-	if err != nil {
-		panic(err)
-	}
-
-	conf.ApplicationConfig = applicationConfig
-
-	fmt.Println("Load config file finish")
-}
-
-func GetConfig() Config {
-	return conf
-}

+ 0 - 3
um/deployment/config/config.yaml

@@ -1,3 +0,0 @@
-api:
-  url_prefix: /um/api
-  port: 10002

+ 2 - 2
tm/application/application.go → utm/application/application.go

@@ -1,8 +1,8 @@
 package application
 
 import (
-	"baize_scaffold/tm/application/service"
-	"baize_scaffold/tm/config"
+	"baize_scaffold/utm/application/service"
+	"baize_scaffold/utm/config"
 
 	"git.sxidc.com/go-framework/baize"
 	"git.sxidc.com/go-framework/baize/framework/core/application"

+ 12 - 0
utm/application/domain/auth/request_params.go

@@ -0,0 +1,12 @@
+package auth
+
+type (
+	LoginJsonBody struct {
+		UserName string `json:"userName" binding:"required"`
+		Password string `json:"password" binding:"required"`
+	}
+
+	CheckTokenJsonBody struct {
+		Token string `json:"token" binding:"required"`
+	}
+)

+ 113 - 0
utm/application/service/auth.go

@@ -0,0 +1,113 @@
+package service
+
+import (
+	"baize_scaffold/utm/application/domain/auth"
+	"baize_scaffold/utm/data_loader"
+	"baize_scaffold/utm/tools"
+
+	"git.sxidc.com/go-framework/baize/framework/binding"
+	"git.sxidc.com/go-framework/baize/framework/core/api"
+	"git.sxidc.com/go-framework/baize/framework/core/api/request"
+	"git.sxidc.com/go-framework/baize/framework/core/api/response"
+	"git.sxidc.com/go-framework/baize/framework/core/application"
+	"git.sxidc.com/go-framework/baize/framework/core/domain"
+	"git.sxidc.com/go-framework/baize/framework/core/infrastructure"
+	"github.com/pkg/errors"
+)
+
+var authService = &AuthService{}
+
+type AuthService struct{}
+
+func (svc *AuthService) Init(appInstance *application.App) error {
+	svc.root(appInstance)
+	svc.v1(appInstance)
+	return nil
+}
+
+func (svc *AuthService) Destroy() error {
+	return nil
+}
+
+func (svc *AuthService) root(appInstance *application.App) {
+	rootBinder := binding.NewBinder(appInstance.ChooseRouter(api.RouterPrefix, ""), nil)
+
+	binding.PostBind(rootBinder, &binding.SimpleBindItem[map[string]any]{
+		Path:             "/login",
+		SendResponseFunc: response.SendMapResponse,
+		RequestParams:    &auth.LoginJsonBody{},
+		ServiceFunc: func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (map[string]any, error) {
+			errResponse := map[string]any{
+				"token": "",
+			}
+
+			jsonBody, err := request.ToConcrete[*auth.LoginJsonBody](params)
+			if err != nil {
+				return errResponse, err
+			}
+
+			user, err := data_loader.GetDataLoader().GetUserByUserNameAndPassword(jsonBody.UserName, jsonBody.Password)
+			if err != nil {
+				return errResponse, err
+			}
+
+			token, err := tools.NewJWT(user.ID, 0)
+			if err != nil {
+				return errResponse, err
+			}
+
+			return map[string]any{
+				"token": token,
+			}, nil
+		},
+	})
+}
+
+func (svc *AuthService) v1(appInstance *application.App) {
+	v1Binder := binding.NewBinder(appInstance.ChooseRouter(api.RouterPrefix, "v1"), nil)
+
+	binding.PostBind(v1Binder, &binding.SimpleBindItem[map[string]any]{
+		Path:             "/checkToken",
+		SendResponseFunc: response.SendMapResponse,
+		RequestParams:    &auth.CheckTokenJsonBody{},
+		ServiceFunc: func(c *api.Context, params request.Params, objects []domain.Object, i *infrastructure.Infrastructure) (map[string]any, error) {
+			errResponse := map[string]any{
+				"tenantId":   "",
+				"tenantName": "",
+				"userId":     "",
+				"userName":   "",
+			}
+
+			jsonBody, err := request.ToConcrete[*auth.CheckTokenJsonBody](params)
+			if err != nil {
+				return errResponse, err
+			}
+
+			valid, userID, err := tools.CheckJWT(jsonBody.Token)
+			if err != nil {
+				return errResponse, err
+			}
+
+			if !valid {
+				return errResponse, errors.New("token无效")
+			}
+
+			user, err := data_loader.GetDataLoader().GetUserByID(userID)
+			if err != nil {
+				return errResponse, err
+			}
+
+			tenant, err := data_loader.GetDataLoader().GetTenantByID(user.CurrentTenantID)
+			if err != nil {
+				return errResponse, err
+			}
+
+			return map[string]any{
+				"tenantId":   tenant.ID,
+				"tenantName": tenant.Name,
+				"userId":     user.ID,
+				"userName":   user.UserName,
+			}, nil
+		},
+	})
+}

+ 3 - 5
um/application/service/service.go → utm/application/service/service.go

@@ -2,13 +2,11 @@ package service
 
 import "git.sxidc.com/go-framework/baize/framework/core/application"
 
-const (
-	dbSchema = "test"
-)
-
 type Service interface {
 	Init(appInstance *application.App) error
 	Destroy() error
 }
 
-var RegisteredServices = []Service{}
+var RegisteredServices = []Service{
+	authService,
+}

+ 0 - 0
tm/config/config.go → utm/config/config.go


+ 151 - 0
utm/data_loader/data_loader.go

@@ -0,0 +1,151 @@
+package data_loader
+
+import (
+	"os"
+	"path/filepath"
+
+	"git.sxidc.com/go-tools/utils/fileutils"
+	"git.sxidc.com/go-tools/utils/strutils"
+	"github.com/pkg/errors"
+	"gopkg.in/yaml.v3"
+)
+
+var dataLoaderInstance *DataLoader
+
+func GetDataLoader() *DataLoader {
+	return dataLoaderInstance
+}
+
+func Init() {
+	dataDir := os.Getenv("DATA_LOADER_DATA_DIR")
+	if strutils.IsStringEmpty(dataDir) {
+		panic("DATA_LOADER_DATA_DIR环境变量未设置")
+	}
+
+	dataDirAbs, err := filepath.Abs(dataDir)
+	if err != nil {
+		panic(err)
+	}
+
+	if !fileutils.PathExists(dataDirAbs) {
+		panic("数据目录不存在")
+	}
+
+	tenantsDataFilePath := filepath.Join(dataDirAbs, "tenants.yaml")
+	if !fileutils.PathExists(tenantsDataFilePath) {
+		panic("租户数据不存在")
+	}
+
+	usersDataFilePath := filepath.Join(dataDirAbs, "users.yaml")
+	if !fileutils.PathExists(usersDataFilePath) {
+		panic("用户数据不存在")
+	}
+
+	rolesDataFilePath := filepath.Join(dataDirAbs, "roles.yaml")
+	if !fileutils.PathExists(rolesDataFilePath) {
+		panic("角色数据不存在")
+	}
+
+	d, err := LoadData(tenantsDataFilePath, usersDataFilePath, rolesDataFilePath)
+	if err != nil {
+		panic(err)
+	}
+
+	dataLoaderInstance = d
+}
+
+type Tenant struct {
+	ID   string `yaml:"id"`
+	Name string `yaml:"name"`
+}
+
+type User struct {
+	ID              string   `yaml:"id"`
+	UserName        string   `yaml:"username"`
+	Password        string   `yaml:"password"`
+	RoleIDs         []string `yaml:"role_ids"`
+	CurrentTenantID string   `yaml:"current_tenant_id"`
+}
+
+type Role struct {
+	ID          string       `yaml:"id"`
+	Name        string       `yaml:"name"`
+	Permissions []Permission `yaml:"permissions"`
+}
+
+type Permission struct {
+	Resource string `yaml:"resource"`
+	Action   string `yaml:"action"`
+}
+
+type DataLoader struct {
+	Tenants []Tenant `yaml:"tenants"`
+	Users   []User   `yaml:"users"`
+	Roles   []Role   `yaml:"roles"`
+}
+
+func LoadData(tenantsDataFilePath string, usersDataFilePath string, rolesDataFilePath string) (*DataLoader, error) {
+	dataLoader := new(DataLoader)
+
+	tenantsData, err := os.ReadFile(tenantsDataFilePath)
+	if err != nil {
+		return nil, err
+	}
+
+	err = yaml.Unmarshal(tenantsData, &dataLoader.Tenants)
+	if err != nil {
+		return nil, err
+	}
+
+	usersData, err := os.ReadFile(usersDataFilePath)
+	if err != nil {
+		return nil, err
+	}
+
+	err = yaml.Unmarshal(usersData, &dataLoader.Users)
+	if err != nil {
+		return nil, err
+	}
+
+	rolesData, err := os.ReadFile(rolesDataFilePath)
+	if err != nil {
+		return nil, err
+	}
+
+	err = yaml.Unmarshal(rolesData, &dataLoader.Roles)
+	if err != nil {
+		return nil, err
+	}
+
+	return dataLoader, nil
+}
+
+func (d *DataLoader) GetUserByUserNameAndPassword(userName string, password string) (User, error) {
+	for _, user := range d.Users {
+		if user.UserName == userName && user.Password == password {
+			return user, nil
+		}
+	}
+
+	return User{}, errors.New("用户名或密码错误")
+}
+
+func (d *DataLoader) GetUserByID(userID string) (User, error) {
+	for _, user := range d.Users {
+		if user.ID == userID {
+			return user, nil
+		}
+	}
+
+	return User{}, errors.New("用户不存在")
+}
+
+func (d *DataLoader) GetTenantByID(tenantID string) (Tenant, error) {
+	for _, tenant := range d.Tenants {
+		if tenant.ID == tenantID {
+			return tenant, nil
+		}
+	}
+
+	return Tenant{}, nil
+}

+ 3 - 0
utm/deployment/config/config.yaml

@@ -0,0 +1,3 @@
+api:
+  url_prefix: /utm/api
+  port: 10002

+ 14 - 0
utm/deployment/data/roles.yaml

@@ -0,0 +1,14 @@
+- id: 06c7aacd14734fb79f2d85390e12ad54
+  name: 管理员
+  permissions:
+    - resource: /xxx/yyy
+      action: POST
+    - resource: /bbb/ccc
+      action: GET
+- id: e26f06abd88d42879f1e64d7cddcc85
+  name: 普通用户
+  permissions:
+    - resource: /xxx1/yyy1
+      action: POST
+    - resource: /bbb1/ccc1
+      action: GET

+ 2 - 0
utm/deployment/data/tenants.yaml

@@ -0,0 +1,2 @@
+- id: 01dedd08065f494498eb0f7893202c36
+  name: 测试租户

+ 12 - 0
utm/deployment/data/users.yaml

@@ -0,0 +1,12 @@
+- id: 88fdbf80928a4529944b48112999921a
+  username: admin
+  password: 123456
+  role_ids:
+    - 06c7aacd14734fb79f2d85390e12ad54
+  current_tenant_id: 01dedd08065f494498eb0f7893202c36
+- id: 5002192dbac44476a4f0c927dab2cf57
+  username: common
+  password: 123456
+  role_ids:
+    - e26f06abd88d42879f1e64d7cddcc85
+  current_tenant_id: 01dedd08065f494498eb0f7893202c36

+ 4 - 1
um/main.go → utm/main.go

@@ -1,13 +1,16 @@
 package main
 
 import (
-	"baize_scaffold/um/application"
+	"baize_scaffold/utm/application"
+	"baize_scaffold/utm/data_loader"
 	"syscall"
 
 	DEATH "github.com/vrecan/death"
 )
 
 func main() {
+	data_loader.Init()
+
 	application.NewApp()
 	defer application.DestroyApp()
 

+ 62 - 0
utm/tools/fsjwt.go

@@ -0,0 +1,62 @@
+package tools
+
+import (
+	"time"
+
+	"github.com/dgrijalva/jwt-go"
+	"github.com/pkg/errors"
+)
+
+const (
+	jwtSecretKey = "@MKU^KNGTF%K^#VJ<TAHCVD#$XZSWQ@L"
+)
+
+func NewJWT(userID string, exp time.Duration) (string, error) {
+	token := jwt.New(jwt.SigningMethodHS256)
+	claims := make(jwt.MapClaims)
+
+	if exp > 0 {
+		claims["exp"] = time.Now().Add(exp * time.Second).Unix()
+	}
+
+	claims["aud"] = userID
+	claims["iat"] = time.Now().Unix()
+	token.Claims = claims
+
+	tokenString, err := token.SignedString([]byte(jwtSecretKey))
+	if err != nil {
+		return "", err
+	}
+
+	return tokenString, nil
+}
+
+func CheckJWT(tokenStr string) (bool, string, error) {
+	token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
+		return []byte(jwtSecretKey), nil
+	})
+	if err != nil {
+		validationErr, ok := err.(*jwt.ValidationError)
+		if !ok {
+			return false, "", err
+		}
+
+		if validationErr.Errors == jwt.ValidationErrorExpired {
+			return false, "", nil
+		}
+
+		return false, "", err
+	}
+
+	claims, ok := token.Claims.(jwt.MapClaims)
+	if !ok {
+		return false, "", errors.New("类型转换失败")
+	}
+
+	userID, ok := claims["aud"].(string)
+	if !ok {
+		return false, "", errors.New("类型转换失败")
+	}
+
+	return token.Valid, userID, nil
+}