hi-server/internal/logic/common/familyEntitlement.go
shanshanzhong f4fe0e32a8
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 8m16s
家庭组逻辑导致支付失败
2026-03-05 00:01:50 -08:00

91 lines
2.7 KiB
Go

package common
import (
"context"
modelUser "github.com/perfect-panel/server/internal/model/user"
"github.com/perfect-panel/server/pkg/xerr"
"github.com/pkg/errors"
"gorm.io/gorm"
)
const (
EntitlementSourceSelf = "self"
EntitlementSourceFamilyOwner = "family_owner"
)
type EntitlementContext struct {
EffectiveUserID int64
Source string
OwnerUserID int64
ReadOnly bool
}
type familyEntitlementRelation struct {
Role uint8 `gorm:"column:role"`
FamilyStatus uint8 `gorm:"column:family_status"`
OwnerUserID int64 `gorm:"column:owner_user_id"`
}
func ResolveEntitlementUser(ctx context.Context, db *gorm.DB, currentUserID int64) (*EntitlementContext, error) {
entitlement := buildEntitlementContext(currentUserID, nil)
if currentUserID <= 0 {
return entitlement, nil
}
var relation familyEntitlementRelation
query := db.WithContext(ctx).
Table("user_family_member").
Select("user_family_member.role, user_family.status AS family_status, user_family.owner_user_id").
Joins("JOIN user_family ON user_family.id = user_family_member.family_id AND user_family.deleted_at IS NULL").
Where("user_family_member.user_id = ? AND user_family_member.deleted_at IS NULL AND user_family_member.status = ?", currentUserID, modelUser.FamilyMemberActive).
Order("user_family_member.role").
Limit(1).
Find(&relation)
if query.Error != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "query family entitlement relation failed")
}
if query.RowsAffected == 0 {
return entitlement, nil
}
return buildEntitlementContext(currentUserID, &relation), nil
}
func DenyIfFamilyMemberReadonly(ctx context.Context, db *gorm.DB, currentUserID int64) error {
entitlement, err := ResolveEntitlementUser(ctx, db, currentUserID)
if err != nil {
return err
}
return denyReadonlyEntitlement(entitlement)
}
func buildEntitlementContext(currentUserID int64, relation *familyEntitlementRelation) *EntitlementContext {
entitlement := &EntitlementContext{
EffectiveUserID: currentUserID,
Source: EntitlementSourceSelf,
}
if relation == nil {
return entitlement
}
if relation.Role == modelUser.FamilyRoleMember &&
relation.FamilyStatus == modelUser.FamilyStatusActive &&
relation.OwnerUserID > 0 &&
relation.OwnerUserID != currentUserID {
return &EntitlementContext{
EffectiveUserID: relation.OwnerUserID,
Source: EntitlementSourceFamilyOwner,
OwnerUserID: relation.OwnerUserID,
ReadOnly: true,
}
}
return entitlement
}
func denyReadonlyEntitlement(entitlement *EntitlementContext) error {
if entitlement != nil && entitlement.ReadOnly {
return errors.Wrapf(xerr.NewErrCode(xerr.FamilyOwnerOperationForbidden), "family member operation is forbidden")
}
return nil
}