u
This commit is contained in:
1 parent
8663cb2e3d
commit
83cbf18572
34 files changed
+1938
-1350
No files matched your search
@@ -6,7 +6,10 @@ import (
|
||||
"allapp/biz/router/middleware"
|
||||
"allapp/db"
|
||||
"allapp/db/repo"
|
||||
"allapp/utils"
|
||||
"allapp/utils/errorx"
|
||||
"allapp/utils/idgen"
|
||||
"allapp/utils/redisx"
|
||||
"allapp/utils/response"
|
||||
"context"
|
||||
|
||||
@@ -16,47 +19,29 @@ import (
|
||||
"github.com/cloudwego/hertz/pkg/protocol/consts"
|
||||
)
|
||||
|
||||
// DissolveSpace .
|
||||
// @router /space/dissolve [POST]
|
||||
func DissolveSpace(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req space.DissolveSpaceParams
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
// KickOutUser 踢出某人
|
||||
// @router /space/kick [POST]
|
||||
func KickOutUser(ctx context.Context, c *app.RequestContext) {
|
||||
var req space.KickOutUserParams
|
||||
if err := c.BindAndValidate(&req); err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
userID := middleware.GetUserID(ctx)
|
||||
spaceByUserId, err := db.Queries.GetSpaceByUserId(ctx, userID)
|
||||
spaceID := middleware.GetSpaceID(ctx)
|
||||
|
||||
hasPermission, err := CheckUserPermission(ctx, userID, spaceID)
|
||||
if err != nil {
|
||||
if errorx.IsNotFound(err) {
|
||||
response.Success(c).Send()
|
||||
return
|
||||
} else {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
if !hasPermission {
|
||||
response.Fail(c).Message("无权限操作").Send()
|
||||
return
|
||||
}
|
||||
|
||||
spaceId := spaceByUserId.ID
|
||||
|
||||
err = db.WithTx(ctx, func(q *repo.Queries) error {
|
||||
err := q.DeleteSpace(ctx, spaceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = q.DeleteSpaceUserAll(ctx, spaceId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
if err := LeaveSpace(ctx, req.UserId, spaceID); err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
@@ -64,20 +49,293 @@ func DissolveSpace(ctx context.Context, c *app.RequestContext) {
|
||||
response.Success(c).Send()
|
||||
}
|
||||
|
||||
// EnterSpace .
|
||||
// @router /space/enter [POST]
|
||||
func EnterSpace(ctx context.Context, c *app.RequestContext) {
|
||||
// QuitSpace .
|
||||
// @router /space/quit [POST]
|
||||
func QuitSpace(ctx context.Context, c *app.RequestContext) {
|
||||
var req space.QuitSpaceParams
|
||||
if err := c.BindAndValidate(&req); err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
userID := middleware.GetUserID(ctx)
|
||||
spaceID := req.SpaceId
|
||||
|
||||
// 检查权限
|
||||
role, exists, err := redisx.GetUserSpaceRole(ctx, userID, spaceID)
|
||||
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if !exists {
|
||||
response.Fail(c).Message("已不在该空间内").Send()
|
||||
return
|
||||
}
|
||||
|
||||
err = db.WithTx(ctx, func(q *repo.Queries) error {
|
||||
if role == 0 {
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
response.Success(c).Send()
|
||||
}
|
||||
|
||||
// JoinSpace .
|
||||
// @router /space/join [POST]
|
||||
func JoinSpace(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req space.EnterSpaceParams
|
||||
var req space.JoinSpaceParams
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(space.EnterSpaceResult)
|
||||
resp := new(space.JoinSpaceResult)
|
||||
|
||||
userID := middleware.GetUserID(ctx)
|
||||
oldSpaceID := middleware.GetSpaceID(ctx)
|
||||
inviteCode := req.InviteCode
|
||||
|
||||
spaceByInviteCode, err := db.Queries.FindSpaceByInviteCode(ctx, inviteCode)
|
||||
if err != nil {
|
||||
if errorx.IsNotFound(err) {
|
||||
response.Fail(c).Message("邀请码错误或已过期").Send()
|
||||
return
|
||||
}
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
joinSpaceID := spaceByInviteCode.ID
|
||||
|
||||
// 检查权限
|
||||
role, exists, err := redisx.GetUserSpaceRole(ctx, userID, oldSpaceID)
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
err = db.WithTx(ctx, func(q *repo.Queries) error {
|
||||
// 判断权限, 如果角色为 0 则解散
|
||||
if exists && role == 0 {
|
||||
users, err2 := q.ListSpaceUsers(ctx, oldSpaceID)
|
||||
|
||||
if err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
if err2 := LeaveSpace(ctx, user.UserID, oldSpaceID); err2 != nil {
|
||||
return err2
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 退出就行
|
||||
if err2 := q.DeleteSpaceUser(ctx, repo.DeleteSpaceUserParams{
|
||||
SpaceID: oldSpaceID,
|
||||
UserID: userID,
|
||||
}); err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
if err2 := redisx.RemoveUserSpace(ctx, userID, oldSpaceID); err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
// 再加入
|
||||
if err2 := q.InsertSpaceUser(ctx, repo.InsertSpaceUserParams{
|
||||
ID: idgen.NextId(),
|
||||
UserID: userID,
|
||||
SpaceID: joinSpaceID,
|
||||
Role: 0,
|
||||
}); err2 != nil {
|
||||
return err2
|
||||
}
|
||||
|
||||
if err2 := redisx.AddOrUpdateUserSpace(ctx, userID, joinSpaceID, 0); err2 != nil {
|
||||
return err2
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
c.JSON(consts.StatusOK, resp)
|
||||
}
|
||||
|
||||
// ListSpaceUsers .
|
||||
// @router /space/users [POST]
|
||||
func ListSpaceUsers(ctx context.Context, c *app.RequestContext) {
|
||||
var err error
|
||||
var req space.ListSpaceUsersParams
|
||||
err = c.BindAndValidate(&req)
|
||||
if err != nil {
|
||||
c.String(consts.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(space.ListSpaceUsersResult)
|
||||
|
||||
// 查询
|
||||
users, err := db.Queries.ListSpaceUsers(ctx, req.SpaceId)
|
||||
if err != nil {
|
||||
errorx.AddError(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
spaceUsers := make([]*space.SpaceUser, 0, len(users))
|
||||
|
||||
for _, user := range users {
|
||||
spaceUsers = append(spaceUsers, &space.SpaceUser{
|
||||
UserId: user.UserID,
|
||||
UserName: user.UserName,
|
||||
UserAvatar: user.UserAvatar,
|
||||
Role: user.Role,
|
||||
})
|
||||
}
|
||||
|
||||
resp.Users = spaceUsers
|
||||
|
||||
response.Success(c).Data(spaceUsers).Send()
|
||||
}
|
||||
|
||||
// CheckUserPermission 检查是否有权限
|
||||
func CheckUserPermission(ctx context.Context, userID int64, spaceID int64) (bool, error) {
|
||||
inSpace, err := redisx.InSpace(ctx, userID, spaceID)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !inSpace {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
role, exists, err := redisx.GetUserSpaceRole(ctx, userID, spaceID)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return role == 0, nil
|
||||
}
|
||||
|
||||
// LeaveSpace 处理用户离开空间逻辑(包括删除空间用户、清理 Redis、创建新空间)
|
||||
func LeaveSpace(ctx context.Context, userID, spaceID int64) error {
|
||||
return db.WithTx(ctx, func(q *repo.Queries) error {
|
||||
// 1. 删除数据库空间用户
|
||||
if err := q.DeleteSpaceUser(ctx, repo.DeleteSpaceUserParams{
|
||||
UserID: userID,
|
||||
SpaceID: spaceID,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 确保该用户加入了缓存
|
||||
err := InitUserSpaces(ctx, userID)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. 删除 Redis 缓存
|
||||
if err := redisx.RemoveUserSpace(ctx, userID, spaceID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 3. 确保用户至少有一个空间
|
||||
if err := EnsureUserHasSpaceWithTx(ctx, q, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// InitUserSpaces 初始化用户空间信息
|
||||
func InitUserSpaces(ctx context.Context, userID int64) error {
|
||||
hasSpace, err := redisx.HasUserSpaces(ctx, userID)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if hasSpace {
|
||||
return nil
|
||||
}
|
||||
|
||||
spaces, err := db.Queries.ListUserSpaces(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
spaceRoles := make(map[int64]int32, len(spaces))
|
||||
for _, row := range spaces {
|
||||
spaceRoles[row.ID] = row.Role
|
||||
}
|
||||
|
||||
return redisx.SetUserSpaces(ctx, userID, spaceRoles)
|
||||
}
|
||||
|
||||
// EnsureUserHasSpaceWithTx 确保用户至少有一个空间,如果没有则创建新空间
|
||||
// 注意:不管理事务,需要在外层传入 q *repo.Queries
|
||||
func EnsureUserHasSpaceWithTx(ctx context.Context, q *repo.Queries, userID int64) error {
|
||||
// 1. 查询用户现有空间
|
||||
spaces, err := redisx.GetUserSpaces(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(spaces) > 0 {
|
||||
// 已经有空间,无需创建
|
||||
return nil
|
||||
}
|
||||
|
||||
// 2. 没有空间则创建
|
||||
var inviteCode string
|
||||
for {
|
||||
code := utils.GenerateCode(6)
|
||||
_, err := q.FindSpaceByInviteCode(ctx, code)
|
||||
if errorx.IsNotFound(err) {
|
||||
inviteCode = code
|
||||
break
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
newSpaceID := idgen.NextId()
|
||||
|
||||
// 插入新空间
|
||||
if err := q.InsertSpace(ctx, repo.InsertSpaceParams{
|
||||
ID: newSpaceID,
|
||||
InviteCode: inviteCode,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 插入空间用户
|
||||
if err := q.InsertSpaceUser(ctx, repo.InsertSpaceUserParams{
|
||||
ID: idgen.NextId(),
|
||||
SpaceID: newSpaceID,
|
||||
UserID: userID,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 同步到 Redis
|
||||
if err := redisx.AddOrUpdateUserSpace(ctx, userID, newSpaceID, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in new issue
Block a user