service.go 11.5 KB
package service

import (
	"errors"
	"time"

	"github.com/linmadan/egglib-go/core/application"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/factory"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/application/mobile/auth/command"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/cache"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/service_gateway/allied_creation_user"
	"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/service_gateway/sms_serve"
)

// 组织管理
type AuthService struct {
}

//AuthLogin 用户登录
func (srv AuthService) AuthLogin(loginCommand *command.LoginCommand) (interface{}, error) {
	var (
		result interface{}
		err    error
	)
	switch loginCommand.GrantType {
	case "signInPassword":
		result, err = srv.SignInPassword(loginCommand.Phone, loginCommand.Password)
	case "signInCaptcha":
		result, err = srv.SignInCaptcha(loginCommand.Phone, loginCommand.Captcha)
	default:
		err = errors.New("登录方式无法解析")
	}
	return result, err
}

//SignInPassword 使用账号密码校验
func (srv AuthService) SignInPassword(account string, password string) (interface{}, error) {
	creationUserGateway := allied_creation_user.NewHttplibAlliedCreationUser(domain.Operator{})
	_, err := creationUserGateway.AuthCheckPassword(allied_creation_user.ReqAuthCheckPassword{
		Password: password,
		Phone:    account,
	})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	ltoken := domain.LoginToken{
		UserId:    0,
		Account:   account,
		Platform:  domain.LoginPlatformApp,
		CompanyId: 0,
	}
	authcode, err := ltoken.GenerateAuthCode()
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	result := map[string]string{
		"authCode": authcode,
	}
	return result, nil
}

//SignInCaptcha 使用手机验证码登录
func (srv AuthService) SignInCaptcha(phone string, captcha string) (interface{}, error) {
	smsServeGateway := sms_serve.NewHttplibHttplibSmsServe()
	err := smsServeGateway.CheckSmsCode(phone, captcha)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	ltoken := domain.LoginToken{
		UserId:    0,
		Account:   phone,
		Platform:  domain.LoginPlatformApp,
		CompanyId: 0,
	}
	authcode, err := ltoken.GenerateAuthCode()
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	result := map[string]string{
		"authCode": authcode,
	}
	return result, nil
}

//GetAuthAccessToken 获取令牌Token
func (srv AuthService) GetAuthAccessToken(accessTokenCommand *command.AccessTokenCommand) (interface{}, error) {
	if err := accessTokenCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	ltoken := domain.LoginToken{}
	err := ltoken.ParseToken(accessTokenCommand.AuthCode)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	phone := ltoken.Account
	creationUserGateway := allied_creation_user.NewHttplibAlliedCreationUser(domain.Operator{})
	userSeachResult, err := creationUserGateway.UserSearch(allied_creation_user.ReqUserSearch{
		Phone: phone,
	})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if len(userSeachResult.Users) == 0 {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, "获取用户信息失败")
	}
	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var loginAccessRepository domain.LoginAccessRepository
	if loginAccessRepository, err = factory.CreateLoginAccessRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	_, lAccess, err := loginAccessRepository.Find(map[string]interface{}{
		"account":  phone,
		"platform": domain.LoginPlatformApp,
	})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	var currentAccess *domain.LoginAccess
	if len(lAccess) > 0 {
		currentAccess = lAccess[0]
		currentAccess.UpdatedTime = time.Now()
	} else {
		currentAccess = &domain.LoginAccess{
			UserBaseId:     int64(userSeachResult.Users[0].UserBaseId),
			UserId:         int64(userSeachResult.Users[0].UserId),
			Account:        userSeachResult.Users[0].UserInfo.Phone,
			Platform:       domain.LoginPlatformApp,
			CompanyId:      int64(userSeachResult.Users[0].Company.CompanyId),
			OrganizationId: int64(userSeachResult.Users[0].Org.OrgId),
			AccessToken:    "",
			RefreshToken:   "",
			AccessExpired:  0,
			RefreshExpired: 0,
			CreatedTime:    time.Now(),
			UpdatedTime:    time.Now(),
		}
	}
	//判定当前凭证的companyId,OrganizationId 是否在用户列表中
	var currentOrgIsOK bool
loopUser1:
	for _, v := range userSeachResult.Users {
		if v.Company.CompanyId == int(currentAccess.CompanyId) {
			for _, vv := range v.UserOrg {
				if vv.OrgID == int(currentAccess.OrganizationId) {
					currentOrgIsOK = true
					break loopUser1
				}
			}
		}
	}
	//记录上一次的登录公司组织信息不可用 ,重置登录记录
	//使用找到的第一个可用的公司组织
	if !currentOrgIsOK {
	loopUser2:
		for _, v := range userSeachResult.Users {
			currentAccess.CompanyId = int64(v.Company.CompanyId)
			for _, vv := range v.UserOrg {
				currentAccess.OrganizationId = int64(vv.OrgID)
				currentOrgIsOK = true
				break loopUser2
			}
		}
	}

	loginToken := domain.LoginToken{
		UserId:    currentAccess.UserId,
		Account:   currentAccess.Account,
		CompanyId: currentAccess.CompanyId,
		OrgId:     currentAccess.OrganizationId,
		Platform:  currentAccess.Platform,
	}

	accessTokenStr, err := loginToken.GenerateAccessToken()
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	currentAccess.AccessToken = accessTokenStr
	currentAccess.AccessExpired = loginToken.ExpiresAt
	refreshTokenStr, err := loginToken.GenerateRefreshToken()
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	currentAccess.RefreshToken = refreshTokenStr
	currentAccess.AccessExpired = loginToken.ExpiresAt
	//先存数据库
	_, err = loginAccessRepository.Save(currentAccess)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	//后处理redis缓存
	tokenCache := cache.LoginTokenCache{}
	tokenCache.RemoveAccessToken(currentAccess.Account, domain.LoginPlatformApp)
	tokenCache.RemoveRefreshToken(currentAccess.Account, domain.LoginPlatformApp)
	tokenCache.SaveAccessToken(currentAccess)
	tokenCache.SaveRefreshToken(currentAccess)
	nowTime := time.Now().Unix()
	return map[string]interface{}{
		"refreshToken": accessTokenStr,
		"accessToken":  refreshTokenStr,
		"expiresIn":    currentAccess.AccessExpired - nowTime,
	}, nil
}

func (srv AuthService) RefreshAuthAccessToken(refreshTokenCommand *command.RefreshTokenCommand) (interface{}, error) {
	if err := refreshTokenCommand.ValidateCommand(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	ltoken := domain.LoginToken{}
	err := ltoken.ParseToken(refreshTokenCommand.RefreshToken)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, "refreshToken 不可用,"+err.Error())
	}
	phone := ltoken.Account
	creationUserGateway := allied_creation_user.NewHttplibAlliedCreationUser(domain.Operator{})
	userSeachResult, err := creationUserGateway.UserSearch(allied_creation_user.ReqUserSearch{
		Phone: phone,
	})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, "用户信息获取失败,"+err.Error())
	}
	//判定当前凭证的companyId,OrganizationId 是否在用户列表中
	var currentOrgIsOK bool
loopUser1:
	for _, v := range userSeachResult.Users {
		if v.Company.CompanyId == int(ltoken.CompanyId) {
			for _, vv := range v.UserOrg {
				if vv.OrgID == int(ltoken.OrgId) {
					currentOrgIsOK = true
					break loopUser1
				}
			}
		}
	}
	if !currentOrgIsOK {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, "登录的公司组织不可用")
	}

	transactionContext, err := factory.CreateTransactionContext(nil)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.StartTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	defer func() {
		transactionContext.RollbackTransaction()
	}()
	var loginAccessRepository domain.LoginAccessRepository
	if loginAccessRepository, err = factory.CreateLoginAccessRepository(map[string]interface{}{
		"transactionContext": transactionContext,
	}); err != nil {
		return nil, application.ThrowError(application.INTERNAL_SERVER_ERROR, err.Error())
	}
	_, lAccess, err := loginAccessRepository.Find(map[string]interface{}{
		"account":  phone,
		"platform": domain.LoginPlatformApp,
	})
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	var currentAccess *domain.LoginAccess
	if len(lAccess) > 0 {
		currentAccess = lAccess[0]
		currentAccess.UpdatedTime = time.Now()
	} else {
		currentAccess = &domain.LoginAccess{
			UserBaseId:     ltoken.UserBaseId,
			UserId:         ltoken.UserId,
			Account:        ltoken.Account,
			Platform:       domain.LoginPlatformApp,
			CompanyId:      ltoken.CompanyId,
			OrganizationId: ltoken.OrgId,
			AccessToken:    "",
			RefreshToken:   "",
			AccessExpired:  0,
			RefreshExpired: 0,
			CreatedTime:    time.Now(),
			UpdatedTime:    time.Now(),
		}
	}
	accessTokenStr, err := ltoken.GenerateAccessToken()
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	currentAccess.AccessToken = accessTokenStr
	currentAccess.AccessExpired = ltoken.ExpiresAt
	refreshTokenStr, err := ltoken.GenerateRefreshToken()
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	currentAccess.RefreshToken = refreshTokenStr
	currentAccess.RefreshExpired = ltoken.ExpiresAt
	//先存数据库
	_, err = loginAccessRepository.Save(currentAccess)
	if err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	if err := transactionContext.CommitTransaction(); err != nil {
		return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
	}
	//后处理redis缓存
	tokenCache := cache.LoginTokenCache{}
	tokenCache.RemoveAccessToken(currentAccess.Account, domain.LoginPlatformApp)
	tokenCache.RemoveRefreshToken(currentAccess.Account, domain.LoginPlatformApp)
	tokenCache.SaveAccessToken(currentAccess)
	tokenCache.SaveRefreshToken(currentAccess)
	nowTime := time.Now().Unix()
	return map[string]interface{}{
		"refreshToken": accessTokenStr,
		"accessToken":  refreshTokenStr,
		"expiresIn":    currentAccess.AccessExpired - nowTime,
	}, nil
}