作者 tangxuhui

更新

package command
type AccessTokenCommand struct {
AuthCode string `json:"authCode"`
}
... ...
package command
type LoginCommand struct {
Phone string `json:"phone"`
GrantType string `json:"grantType"` //登录方式(signInPassword 密码登录、signInCaptcha 验证码登录)
Password string `json:"password"`
Captcha string `json:"captcha"`
}
... ...
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/service_gateway/allied_creation_user"
)
// 组织管理
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":
default:
err = errors.New("登录方式无法解析")
}
return result, err
}
//SignInPassword 使用账号密码校验
func (srv AuthService) SignInPassword(account string, password string) (interface{}, error) {
creationUserGateway := allied_creation_user.NewHttplibAlliedCreationUser(0, 0, 0)
_, 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) {
return nil, nil
}
//GetAuthAccessToken 获取令牌Token
func (srv AuthService) GetAuthAccessToken(accessTokenCommand *command.AccessTokenCommand) (interface{}, 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(0, 0, 0)
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(),
}
}
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
//先存数据库
if err := transactionContext.CommitTransaction(); err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
}
//先删缓存
//后加缓存
return nil, nil
}
... ...
package query
type GetAccessTokenCommand struct {
AuthCode string `json:"authCode"`
}
func (cmd GetAccessTokenCommand) Valid() error {
return nil
}
package services
import (
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/sony/sonyflake"
)
var idwork *sonyflake.Sonyflake
func init() {
setting := sonyflake.Settings{
MachineID: func() (uint16, error) {
return 1, nil
},
CheckMachineID: func(u uint16) bool {
return true
},
}
idwork = sonyflake.NewSonyflake(setting)
}
const (
qrcodeExpires int64 = 3600 //二维码的有效时长,单位:秒
qrcodeSecret string = "27e6741f0e0b658c"
)
type qrcodeMessage struct {
Key string `json:"key"`
jwt.StandardClaims
}
func (msg *qrcodeMessage) GenrateToken() (string, error) {
id, err := idwork.NextID()
if err != nil {
return "", fmt.Errorf("生成二维信息失败:%w", err)
}
msg.Key = fmt.Sprint(id)
//TODO jwt
return "", nil
}
func (msg *qrcodeMessage) ParseToken(token string) error {
//TODO jwt
return nil
}
package services
import (
"bytes"
"context"
"encoding/base64"
"image/png"
"github.com/boombuler/barcode"
"github.com/boombuler/barcode/qr"
)
//LoginAccessService 登录功能
type LoginAccessService struct {
}
//LoginByAccount 账号登录获取authcode和可选择列表
func (srv LoginAccessService) LoginByAccount(ctx context.Context) error {
return nil
}
//LoginBySmsCode 短信验证码登录获取authcode和可选择列表
func (srv LoginAccessService) LoginBySmsCode(ctx context.Context) error {
return nil
}
//LoginByAuthCode 使用authCode进行登录获取accessToken和用户权限信息
func (srv LoginAccessService) LoginInfoByAuthCode(ctx context.Context) error {
return nil
}
//GetQrcodeLogin 获取用于登录的二维码以及相应的key数据
func (srv LoginAccessService) GetQrcodeForLogin(ctx context.Context) error {
qrCode, err := qr.Encode("Hello World", qr.M, qr.Auto)
if err != nil {
return err
}
// Scale the barcode to 200x200 pixels
qrCode, err = barcode.Scale(qrCode, 200, 200)
if err != nil {
return err
}
var imgByte bytes.Buffer
// encode the barcode as png
err = png.Encode(&imgByte, qrCode)
if err != nil {
return err
}
imgBase64 := base64.StdEncoding.EncodeToString(imgByte.Bytes())
_ = imgBase64
return err
}
//ValidLoginForQrcode 检查以扫描二维码方式进行登录的状态
func (srv LoginAccessService) LoginByScanQrcode(ctx context.Context) error {
return nil
}
// ValidToken 检查token信息
func (srv LoginAccessService) ValidAccessToken(ctx context.Context) error {
return nil
}
// AuthCodeToAccessToken 用authcode交换accessToken
func (srv LoginAccessService) AuthCodeToAccessToken(ctx context.Context) error {
return nil
}
... ... @@ -7,5 +7,11 @@ type RoleItem struct {
RoleName string `json:"roleName"`
Describe string `json:"describe"`
OrgName string `json:"orgName"`
RoleType int `json:"roleType"`
RoleType int `json:"roleType"` //角色类型 1.普通角色 1024:超级管理员
}
type RoleUser struct {
DepartmentName string `json:"departmentName"`
UserId string `json:"userId"`
UserName string `json:"userName"`
}
... ...
... ... @@ -155,8 +155,8 @@ func (rolesService *RolesService) RoleRemove(roleRemoveCommand *command.RoleRemo
roleIds = append(roleIds, int64(id))
}
}
_, err := creationUserGateway.RoleRemove(allied_creation_user.ReqRoleRemove{
//TODO 修改 为 切片类型
_, err := creationUserGateway.RoleBatchRemove(allied_creation_user.ReqRoleBatchRemove{
RoleIds: roleIds,
})
if err != nil {
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
... ...
... ... @@ -126,11 +126,11 @@ func (usersService *UsersService) CompanyUserAdd(companyUserAddCommand *command.
UserRole: userRole,
// 启用状态(启用:1 禁用:2)
EnableStatus: companyUserAddCommand.EnableStatus,
Password: "",
UserName: companyUserAddCommand.UsersName,
Phone: companyUserAddCommand.Phone,
Avatar: companyUserAddCommand.Avator,
Email: companyUserAddCommand.Avator,
Password: "", //TODO 填充密码
})
data := struct {
... ... @@ -201,7 +201,7 @@ func (usersService *UsersService) CompanyUserResetPassword(companyUserResetPassw
companyUserResetPasswordCommand.Operator.OrgId,
companyUserResetPasswordCommand.Operator.UserId)
_, err := creationUserGateway.UserBatchResetPassword(allied_creation_user.ReqBatchResetPasswordUser{
Password: "",
Password: "", //TODO 填充密码
UserIds: companyUserResetPasswordCommand.UsersIds,
})
return companyUserResetPasswordCommand, err
... ... @@ -358,7 +358,7 @@ func (usersService *UsersService) CooperationUserResetPassword(cooperationUserRe
cooperationUserResetPasswordCommand.Operator.OrgId,
cooperationUserResetPasswordCommand.Operator.UserId)
_, err := creationUserGateway.UserBatchResetPassword(allied_creation_user.ReqBatchResetPasswordUser{
Password: "",
Password: "", //TODO 填充密码
UserIds: cooperationUserResetPasswordCommand.UsersIds,
})
return cooperationUserResetPasswordCommand, err
... ...
... ... @@ -2,6 +2,7 @@ package domain
import "time"
//TODO 移除文件
// 公司信息
type CompanyInfo struct {
CompanyId string `json:"companyId"`
... ...
package domain
//TODO 移除文件
type CooperationInfo struct {
// 共创公司
CooperationCompany string `json:"cooperationCompany"`
... ...
package domain
//TODO 移除文件
// 部门
type Department struct {
// 组织ID
... ...
package domain
//TODO 移除文件
//Dictionary 字典
type Dictionary struct {
// 字典编号 主键
... ...
package domain
//TODO 移除文件
//DictionaryItem 字典明细项
type DictionaryItem struct {
// 项编码
... ...
... ... @@ -2,9 +2,17 @@ package domain
import "time"
//登录的平台
const (
LoginPlatformApp string = "app"
LoginPlatformWeb string = "web"
)
// 登录凭证存储
type LoginAccess struct {
LoginAccessId int64 `json:"loginAccessId"`
UserBaseId int64 `json:"userBaseId"`
UserId int64 `json:"userId"`
// 账号
Account string `json:"account"`
// 对应平台
... ... @@ -17,9 +25,9 @@ type LoginAccess struct {
AccessToken string `json:"accessToken"`
// 刷新登录凭证
RefreshToken string `json:"refreshToken"`
// 登录凭证期时间,时间戳精度秒
// 登录凭证期时间,时间戳精度秒
AccessExpired int64 `json:"accessExpired"`
// 刷新登录凭证期时间,时间戳精度秒
// 刷新登录凭证期时间,时间戳精度秒
RefreshExpired int64 `json:"refreshExpired"`
// 创建时间
CreatedTime time.Time `json:"createdTime"`
... ...
package domain
import (
"time"
jwt "github.com/dgrijalva/jwt-go"
)
const (
loginTokenSecret string = "bbe35ad433dd8e67"
loginTokenSecret string = "bbe35ad433dd8e67"
accessTokenExpiresAt int64 = 60 * 60 * 2 //两个小时过期
refreshTokenExpiresAt int64 = 3600 * 24 * 30 * 1 //刷新token 一个月过期
authCodeExpire int64 = 60 * 15 //15分钟过期
)
type LoginToken struct {
UserId int64 `json:"userId"`
UserBaseId int64 `json:"userBaseId"`
jwt.StandardClaims
UserId int64 `json:"userId"`
// 账号
Account string `json:"account"`
// 对应平台
... ... @@ -14,18 +23,59 @@ type LoginToken struct {
// 公司id
CompanyId int64 `json:"companyId"`
// 组织id
OrgId int64 `json:"orgId"`
}
func (t *LoginToken) GenerateAccessToken() error {
return nil
func (t *LoginToken) GenerateAccessToken() (string, error) {
nowTime := time.Now().Unix()
t.StandardClaims = jwt.StandardClaims{
NotBefore: nowTime,
IssuedAt: nowTime,
ExpiresAt: nowTime + accessTokenExpiresAt,
Issuer: "allied_creation_gateway",
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, *t)
return token.SignedString([]byte(loginTokenSecret))
}
func (t *LoginToken) GenerateRefreshToken() error {
func (t *LoginToken) GenerateRefreshToken() (string, error) {
nowTime := time.Now().Unix()
t.StandardClaims = jwt.StandardClaims{
NotBefore: nowTime,
IssuedAt: nowTime,
ExpiresAt: nowTime + accessTokenExpiresAt,
Issuer: "allied_creation_gateway",
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, *t)
return token.SignedString([]byte(loginTokenSecret))
}
return nil
func (t *LoginToken) GenerateAuthCode() (string, error) {
nowTime := time.Now().Unix()
claims := LoginToken{
StandardClaims: jwt.StandardClaims{
NotBefore: nowTime,
IssuedAt: nowTime,
ExpiresAt: nowTime + authCodeExpire,
Issuer: "allied_creation_gateway",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(loginTokenSecret))
}
func (t *LoginToken) ParseToken(str string) error {
tokenClaims, err := jwt.ParseWithClaims(
str,
&LoginToken{},
func(token *jwt.Token) (interface{}, error) {
return loginTokenSecret, nil
})
if err != nil {
return err
}
if claim, ok := tokenClaims.Claims.(*LoginToken); ok && tokenClaims.Valid {
*t = *claim
}
return nil
}
... ...
package domain
//TODO 移除文件
// 系统菜单
type Menu struct {
// 菜单编号
... ...
package domain
//TODO 移除文件
// 组织organization
type Orgs struct {
// 组织ID
... ...
package domain
//TODO 移除文件
// 区域信息值对象
type RegionInfo struct {
// 区域编号
... ...
package domain
//TODO 移除文件
// 角色 (base)
type Roles struct {
// 角色ID
... ...
package domain
//TODO 移除文件
// 用户基础信息
type Users struct {
// 用户id
... ...
... ... @@ -2,6 +2,7 @@ package domain
import "time"
//TODO 移除文件
// 用户基础信息
type UsersBase struct {
UserId string `json:"userId"`
... ...
package cache
//验证码缓存
... ...
package cache
import "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain"
import (
"time"
type LoginAccessCache struct {
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain"
)
//登录凭证缓存
type LoginTokenCache struct {
}
func (ca LoginTokenCache) keyAccessToken(account string, platform string) string {
str := KEY_PREFIX + "accesstoken:" + account + ":" + platform
return str
}
func (ca LoginTokenCache) keyRefreshToken(account string, platform string) string {
str := KEY_PREFIX + "refreshtoken" + account + ":" + platform
return str
}
func (ca LoginTokenCache) SaveAccessToken(access *domain.LoginAccess) error {
nowTime := time.Now().Unix()
exp := access.AccessExpired - nowTime
if exp <= 0 {
exp = 60 * 60 * 2
}
key := ca.keyAccessToken(access.Account, access.Platform)
result := clientRedis.Set(key, access.AccessToken, time.Duration(exp))
return result.Err()
}
func (ca LoginTokenCache) RemoveAccessToken(account string, platform string) error {
key := ca.keyAccessToken(account, platform)
result := clientRedis.Del(key)
return result.Err()
}
func (ca LoginAccessCache) Save(param *domain.LoginAccess) (*domain.LoginAccess, error) {
return nil, nil
func (ca LoginTokenCache) GetAccessToken(account string, platform string) (string, error) {
key := ca.keyAccessToken(account, platform)
result := clientRedis.Get(key)
return result.Result()
}
func (ca LoginAccessCache) Remove(param *domain.LoginAccess) (*domain.LoginAccess, error) {
return nil, nil
func (ca LoginTokenCache) SaveRefreshToken(access *domain.LoginAccess) error {
nowTime := time.Now().Unix()
exp := access.RefreshExpired - nowTime
if exp <= 0 {
exp = 60 * 60 * 2
}
key := ca.keyAccessToken(access.Account, access.Platform)
result := clientRedis.Set(key, access.RefreshToken, time.Duration(exp))
return result.Err()
}
func (ca LoginTokenCache) RemoveRefreshToken(account string, platform string) error {
key := ca.keyRefreshToken(account, platform)
result := clientRedis.Del(key)
return result.Err()
}
func (ca LoginAccessCache) FindOne(account string, platform string) (*domain.LoginAccess, error) {
return nil, nil
func (ca LoginTokenCache) GetRefreshToken(account string, platform string) (string, error) {
key := ca.keyRefreshToken(account, platform)
result := clientRedis.Get(key)
return result.Result()
}
... ...
package cache
//二维码信息缓存
type LoginQrcodeCache struct {
}
... ...
... ... @@ -9,7 +9,7 @@ import (
var clientRedis *redis.Client
const (
keyPrefix string = "gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway"
KEY_PREFIX string = "allied:creation:gateway:"
)
func Init() *redis.Client {
... ...
package repository
import (
"github.com/linmadan/egglib-go/utils/snowflake"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/log"
)
var idWorker *snowflake.IdWorker
func init() {
worker, err := snowflake.NewIdWorker(1)
if err != nil {
log.Logger.Panic("idWorker init err" + err.Error())
return
}
idWorker = worker
}
... ...
... ... @@ -6,7 +6,6 @@ import (
"github.com/go-pg/pg/v10"
"github.com/linmadan/egglib-go/persistent/pg/sqlbuilder"
pgTransaction "github.com/linmadan/egglib-go/transaction/pg"
"github.com/linmadan/egglib-go/utils/snowflake"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/domain"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/pg/models"
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-gateway/pkg/infrastructure/pg/transform"
... ... @@ -17,11 +16,7 @@ type LoginAccessRepository struct {
}
func (repository *LoginAccessRepository) nextIdentify() (int64, error) {
IdWorker, err := snowflake.NewIdWorker(1)
if err != nil {
return 0, err
}
id, err := IdWorker.NextId()
id, err := idWorker.NextId()
return id, err
}
func (repository *LoginAccessRepository) Save(loginAccess *domain.LoginAccess) (*domain.LoginAccess, error) {
... ... @@ -143,6 +138,8 @@ func (repository *LoginAccessRepository) Find(queryOptions map[string]interface{
query := sqlbuilder.BuildQuery(tx.Model(&loginAccessModels), queryOptions)
query.SetOffsetAndLimit(20)
query.SetOrderDirect("login_access_id", "DESC")
query.SetWhereByQueryOption("account", "account")
query.SetWhereByQueryOption("platform", "platform")
if count, err := query.SelectAndCount(); err != nil {
return 0, loginAccesss, err
} else {
... ...
... ... @@ -229,6 +229,37 @@ func (gateway HttplibAlliedCreationUser) RoleRemove(param ReqRoleRemove) (*DataR
return &data, err
}
// RoleRemove 批量移除角色
func (gateway HttplibAlliedCreationUser) RoleBatchRemove(param ReqRoleBatchRemove) (*DataRoleBatchRemove, error) {
urlStr := gateway.baseUrL + "/role/batch-delete"
method := "post"
req := gateway.CreateRequest(urlStr, method)
log.Logger.Debug("向用户模块请求数据:批量移除角色。", map[string]interface{}{
"api": method + ":" + urlStr,
"param": param,
})
req, err := req.JSONBody(param)
if err != nil {
return nil, fmt.Errorf("请求批量移除角色失败:%w", err)
}
byteResult, err := req.Bytes()
if err != nil {
return nil, fmt.Errorf("获取批量移除角色失败:%w", err)
}
log.Logger.Debug("获取用户模块请求数据:批量移除角色。", map[string]interface{}{
"result": string(byteResult),
})
var result service_gateway.GatewayResponse
err = json.Unmarshal(byteResult, &result)
if err != nil {
return nil, fmt.Errorf("解析批量移除角色:%w", err)
}
var data DataRoleBatchRemove
err = gateway.GetResponseData(result, &data)
return &data, err
}
// RoleGetRelatedUser 获取角色相关联的用户
func (gateway HttplibAlliedCreationUser) RoleGetRelatedUser(param ReqRoleGetRelatedUser) (*DataRoleGetRelatedUser, error) {
orgId := strconv.FormatInt(param.OrgId, 10)
... ...
... ... @@ -30,9 +30,12 @@ type (
//手机账号密码检查
type (
ReqAuthCheckPassword struct {
Password string `json:"password"`
Phone string `json:"phone"`
}
DataAuthCheckPassword struct {
UserId int `json:"userId"`
}
)
... ...
... ... @@ -36,7 +36,7 @@ type (
OrgID int `json:"orgId"`
RoleID int `json:"roleId"`
RoleName string `json:"roleName"`
RoleType int `json:"roleType"`
RoleType int `json:"roleType"` //角色类型 1.普通角色 1024:超级管理员
UpdatedAt string `json:"updatedAt"`
} `json:"role"`
}
... ... @@ -130,6 +130,16 @@ type (
}
)
//批量移除角色
type (
ReqRoleBatchRemove struct {
RoleIds []int64 `json:"roleIds"`
}
DataRoleBatchRemove struct {
}
)
//获取角色相关联的用户
type (
ReqRoleGetRelatedUser struct {
... ... @@ -139,6 +149,16 @@ type (
}
DataRoleGetRelatedUser struct {
NotInRoleUser []struct {
DepartmentName string `json:"departmentName"`
UserID int `json:"userId"`
UserName string `json:"userName"`
} `json:"notInRoleUser"`
RoleUser []struct {
DepartmentName string `json:"departmentName"`
UserID int `json:"userId"`
UserName string `json:"userName"`
} `json:"roleUser"`
}
)
... ...