Files
quyun-v2/backend/app/services/tenant_member_test.go

305 lines
9.3 KiB
Go

package services
import (
"errors"
"time"
"quyun/v2/app/errorx"
tenant_dto "quyun/v2/app/http/v1/dto"
"quyun/v2/database"
"quyun/v2/database/models"
"quyun/v2/pkg/consts"
. "github.com/smartystreets/goconvey/convey"
"go.ipao.vip/gen/types"
)
func (s *TenantTestSuite) Test_ApplyJoin() {
Convey("ApplyJoin", s.T(), func() {
ctx := s.T().Context()
setup := func() (*models.Tenant, *models.User, *models.User) {
database.Truncate(ctx, s.DB,
models.TableNameTenantJoinRequest,
models.TableNameTenantUser,
models.TableNameTenant,
models.TableNameUser,
)
owner := &models.User{Username: "owner_apply", Phone: "13900001001"}
user := &models.User{Username: "user_apply", Phone: "13900001002"}
_ = models.UserQuery.WithContext(ctx).Create(owner)
_ = models.UserQuery.WithContext(ctx).Create(user)
tenant := &models.Tenant{
Name: "Tenant Apply",
UserID: owner.ID,
Status: consts.TenantStatusVerified,
}
_ = models.TenantQuery.WithContext(ctx).Create(tenant)
return tenant, owner, user
}
Convey("should create pending join request", func() {
tenant, _, user := setup()
err := Tenant.ApplyJoin(ctx, tenant.ID, user.ID, &tenant_dto.TenantJoinApplyForm{Reason: "想加入"})
So(err, ShouldBeNil)
req, err := models.TenantJoinRequestQuery.WithContext(ctx).
Where(models.TenantJoinRequestQuery.TenantID.Eq(tenant.ID),
models.TenantJoinRequestQuery.UserID.Eq(user.ID)).
First()
So(err, ShouldBeNil)
So(req.Status, ShouldEqual, string(consts.TenantJoinRequestStatusPending))
})
Convey("should reject duplicate apply", func() {
tenant, _, user := setup()
_ = Tenant.ApplyJoin(ctx, tenant.ID, user.ID, &tenant_dto.TenantJoinApplyForm{})
err := Tenant.ApplyJoin(ctx, tenant.ID, user.ID, &tenant_dto.TenantJoinApplyForm{})
So(err, ShouldNotBeNil)
var appErr *errorx.AppError
So(errors.As(err, &appErr), ShouldBeTrue)
So(appErr.Code, ShouldEqual, errorx.ErrBadRequest.Code)
})
Convey("should reject when already member", func() {
tenant, _, user := setup()
_ = models.TenantUserQuery.WithContext(ctx).Create(&models.TenantUser{
TenantID: tenant.ID,
UserID: user.ID,
Role: types.Array[consts.TenantUserRole]{consts.TenantUserRoleMember},
Status: consts.UserStatusVerified,
})
err := Tenant.ApplyJoin(ctx, tenant.ID, user.ID, &tenant_dto.TenantJoinApplyForm{})
So(err, ShouldNotBeNil)
var appErr *errorx.AppError
So(errors.As(err, &appErr), ShouldBeTrue)
So(appErr.Code, ShouldEqual, errorx.ErrBadRequest.Code)
})
})
}
func (s *TenantTestSuite) Test_CancelJoin() {
Convey("CancelJoin", s.T(), func() {
ctx := s.T().Context()
setup := func() (*models.Tenant, *models.User, *models.User, *models.TenantJoinRequest) {
database.Truncate(ctx, s.DB,
models.TableNameTenantJoinRequest,
models.TableNameTenantUser,
models.TableNameTenant,
models.TableNameUser,
)
owner := &models.User{Username: "owner_cancel", Phone: "13900001003"}
user := &models.User{Username: "user_cancel", Phone: "13900001004"}
_ = models.UserQuery.WithContext(ctx).Create(owner)
_ = models.UserQuery.WithContext(ctx).Create(user)
tenant := &models.Tenant{
Name: "Tenant Cancel",
UserID: owner.ID,
Status: consts.TenantStatusVerified,
}
_ = models.TenantQuery.WithContext(ctx).Create(tenant)
req := &models.TenantJoinRequest{
TenantID: tenant.ID,
UserID: user.ID,
Status: string(consts.TenantJoinRequestStatusPending),
Reason: "测试取消",
}
_ = models.TenantJoinRequestQuery.WithContext(ctx).Create(req)
return tenant, owner, user, req
}
Convey("should cancel pending request", func() {
tenant, _, user, _ := setup()
err := Tenant.CancelJoin(ctx, tenant.ID, user.ID)
So(err, ShouldBeNil)
exists, err := models.TenantJoinRequestQuery.WithContext(ctx).
Where(models.TenantJoinRequestQuery.TenantID.Eq(tenant.ID),
models.TenantJoinRequestQuery.UserID.Eq(user.ID)).
Exists()
So(err, ShouldBeNil)
So(exists, ShouldBeFalse)
})
Convey("should return not found when request missing", func() {
tenant, _, user, _ := setup()
_ = Tenant.CancelJoin(ctx, tenant.ID, user.ID)
err := Tenant.CancelJoin(ctx, tenant.ID, user.ID)
So(err, ShouldNotBeNil)
var appErr *errorx.AppError
So(errors.As(err, &appErr), ShouldBeTrue)
So(appErr.Code, ShouldEqual, errorx.ErrRecordNotFound.Code)
})
})
}
func (s *TenantTestSuite) Test_ReviewJoin() {
Convey("ReviewJoin", s.T(), func() {
ctx := s.T().Context()
setup := func() (*models.Tenant, *models.User, *models.User, *models.TenantJoinRequest) {
database.Truncate(ctx, s.DB,
models.TableNameTenantJoinRequest,
models.TableNameTenantUser,
models.TableNameTenant,
models.TableNameUser,
)
owner := &models.User{Username: "owner_review", Phone: "13900001005"}
user := &models.User{Username: "user_review", Phone: "13900001006"}
_ = models.UserQuery.WithContext(ctx).Create(owner)
_ = models.UserQuery.WithContext(ctx).Create(user)
tenant := &models.Tenant{
Name: "Tenant Review",
UserID: owner.ID,
Status: consts.TenantStatusVerified,
}
_ = models.TenantQuery.WithContext(ctx).Create(tenant)
req := &models.TenantJoinRequest{
TenantID: tenant.ID,
UserID: user.ID,
Status: string(consts.TenantJoinRequestStatusPending),
Reason: "测试审核",
}
_ = models.TenantJoinRequestQuery.WithContext(ctx).Create(req)
return tenant, owner, user, req
}
Convey("should approve join request", func() {
tenant, owner, user, req := setup()
err := Tenant.ReviewJoin(ctx, tenant.ID, owner.ID, req.ID, &tenant_dto.TenantJoinReviewForm{
Action: "approve",
Reason: "通过",
})
So(err, ShouldBeNil)
req, err = models.TenantJoinRequestQuery.WithContext(ctx).Where(models.TenantJoinRequestQuery.ID.Eq(req.ID)).First()
So(err, ShouldBeNil)
So(req.Status, ShouldEqual, string(consts.TenantJoinRequestStatusApproved))
exists, err := models.TenantUserQuery.WithContext(ctx).
Where(models.TenantUserQuery.TenantID.Eq(tenant.ID),
models.TenantUserQuery.UserID.Eq(user.ID)).
Exists()
So(err, ShouldBeNil)
So(exists, ShouldBeTrue)
})
Convey("should reject join request", func() {
tenant, owner, _, req := setup()
err := Tenant.ReviewJoin(ctx, tenant.ID, owner.ID, req.ID, &tenant_dto.TenantJoinReviewForm{
Action: "reject",
Reason: "不符合条件",
})
So(err, ShouldBeNil)
req, err = models.TenantJoinRequestQuery.WithContext(ctx).Where(models.TenantJoinRequestQuery.ID.Eq(req.ID)).First()
So(err, ShouldBeNil)
So(req.Status, ShouldEqual, string(consts.TenantJoinRequestStatusRejected))
})
})
}
func (s *TenantTestSuite) Test_CreateInvite() {
Convey("CreateInvite", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB,
models.TableNameTenantInvite,
models.TableNameTenantUser,
models.TableNameTenant,
models.TableNameUser,
)
owner := &models.User{Username: "owner_invite", Phone: "13900001007"}
_ = models.UserQuery.WithContext(ctx).Create(owner)
tenant := &models.Tenant{
Name: "Tenant Invite",
UserID: owner.ID,
Status: consts.TenantStatusVerified,
}
_ = models.TenantQuery.WithContext(ctx).Create(tenant)
expiresAt := time.Now().Add(24 * time.Hour).Format(time.RFC3339)
item, err := Tenant.CreateInvite(ctx, tenant.ID, owner.ID, &tenant_dto.TenantInviteCreateForm{
MaxUses: 2,
ExpiresAt: &expiresAt,
Remark: "测试邀请",
})
So(err, ShouldBeNil)
So(item.Code, ShouldNotBeBlank)
invite, err := models.TenantInviteQuery.WithContext(ctx).Where(models.TenantInviteQuery.ID.Eq(item.ID)).First()
So(err, ShouldBeNil)
So(invite.MaxUses, ShouldEqual, 2)
So(invite.Status, ShouldEqual, string(consts.TenantInviteStatusActive))
})
}
func (s *TenantTestSuite) Test_AcceptInvite() {
Convey("AcceptInvite", s.T(), func() {
ctx := s.T().Context()
database.Truncate(ctx, s.DB,
models.TableNameTenantInvite,
models.TableNameTenantUser,
models.TableNameTenant,
models.TableNameUser,
)
owner := &models.User{Username: "owner_accept", Phone: "13900001008"}
user := &models.User{Username: "user_accept", Phone: "13900001009"}
_ = models.UserQuery.WithContext(ctx).Create(owner)
_ = models.UserQuery.WithContext(ctx).Create(user)
tenant := &models.Tenant{
Name: "Tenant Accept",
UserID: owner.ID,
Status: consts.TenantStatusVerified,
}
_ = models.TenantQuery.WithContext(ctx).Create(tenant)
invite := &models.TenantInvite{
TenantID: tenant.ID,
UserID: owner.ID,
Code: "invite_accept",
Status: string(consts.TenantInviteStatusActive),
MaxUses: 1,
UsedCount: 0,
ExpiresAt: time.Now().Add(24 * time.Hour),
Remark: "测试使用",
}
_ = models.TenantInviteQuery.WithContext(ctx).Create(invite)
err := Tenant.AcceptInvite(ctx, tenant.ID, user.ID, &tenant_dto.TenantInviteAcceptForm{Code: "invite_accept"})
So(err, ShouldBeNil)
exists, err := models.TenantUserQuery.WithContext(ctx).
Where(models.TenantUserQuery.TenantID.Eq(tenant.ID),
models.TenantUserQuery.UserID.Eq(user.ID)).
Exists()
So(err, ShouldBeNil)
So(exists, ShouldBeTrue)
invite, err = models.TenantInviteQuery.WithContext(ctx).Where(models.TenantInviteQuery.ID.Eq(invite.ID)).First()
So(err, ShouldBeNil)
So(invite.UsedCount, ShouldEqual, 1)
})
}