ente/server/pkg/controller/family/family.go
2024-03-01 13:37:01 +05:30

142 lines
4.5 KiB
Go

package family
import (
"context"
"errors"
"fmt"
"github.com/ente-io/museum/pkg/controller/usercache"
"github.com/ente-io/museum/pkg/utils/time"
"github.com/ente-io/museum/ente"
"github.com/ente-io/museum/pkg/controller"
"github.com/ente-io/museum/pkg/repo"
"github.com/sirupsen/logrus"
"github.com/ente-io/stacktrace"
)
const (
// maxFamilyMemberLimit number of folks who can be part of a family
maxFamilyMemberLimit = 6
)
// Controller exposes functions to interact with family module
type Controller struct {
BillingCtrl *controller.BillingController
UserRepo *repo.UserRepository
FamilyRepo *repo.FamilyRepository
UserCacheCtrl *usercache.Controller
}
// FetchMembers return list of members who are part of a family plan
func (c *Controller) FetchMembers(ctx context.Context, userID int64) (ente.FamilyMemberResponse, error) {
user, err := c.UserRepo.Get(userID)
if err != nil {
return ente.FamilyMemberResponse{}, stacktrace.Propagate(err, "")
}
if user.FamilyAdminID == nil {
return ente.FamilyMemberResponse{}, stacktrace.Propagate(ente.ErrBadRequest, "user is not part of any family plan")
}
return c.FetchMembersForAdminID(ctx, *user.FamilyAdminID)
}
func (c *Controller) FetchMembersForAdminID(ctx context.Context, familyAdminID int64) (ente.FamilyMemberResponse, error) {
familyMembers, err := c.FamilyRepo.GetMembersWithStatus(familyAdminID, repo.ActiveOrInvitedFamilyMemberStatus)
if err != nil {
return ente.FamilyMemberResponse{}, stacktrace.Propagate(err, "")
}
memberUserIDs := make([]int64, 0)
for _, familyMember := range familyMembers {
memberUserIDs = append(memberUserIDs, familyMember.MemberUserID)
}
if len(memberUserIDs) == 0 {
return ente.FamilyMemberResponse{}, stacktrace.Propagate(errors.New("member could can not be zero"), "")
}
usersUsageWithSubData, err := c.UserRepo.GetUserUsageWithSubData(ctx, memberUserIDs)
if err != nil {
return ente.FamilyMemberResponse{}, err
}
var adminSubStorage, adminSubExpiryTime int64
for i := 0; i < len(familyMembers); i++ {
member := &familyMembers[i]
for _, userUsageData := range usersUsageWithSubData {
if member.MemberUserID == userUsageData.UserID {
member.Email = *userUsageData.Email
// return usage only if the member is part of family group
if member.Status == ente.ACCEPTED || member.Status == ente.SELF {
member.Usage = userUsageData.StorageConsumed
}
if member.IsAdmin {
adminSubStorage = userUsageData.Storage
adminSubExpiryTime = userUsageData.ExpiryTime
}
}
}
}
bonus, err := c.UserCacheCtrl.GetActiveStorageBonus(ctx, familyAdminID)
if err != nil {
return ente.FamilyMemberResponse{}, err
}
adminUsableBonus := int64(0)
if adminSubExpiryTime < time.Microseconds() {
adminUsableBonus = bonus.GetUsableBonus(0)
} else {
adminUsableBonus = bonus.GetUsableBonus(adminSubExpiryTime)
}
return ente.FamilyMemberResponse{
Members: familyMembers,
Storage: adminSubStorage, // family plan storage
ExpiryTime: adminSubExpiryTime,
AdminBonus: adminUsableBonus,
}, nil
}
func (c *Controller) HandleAccountDeletion(ctx context.Context, userID int64, logger *logrus.Entry) error {
user, err := c.UserRepo.Get(userID)
if err != nil {
return stacktrace.Propagate(err, "")
}
if user.FamilyAdminID == nil {
logger.Info("not part of any family, declining any pending invite")
err = c.FamilyRepo.DeclineAnyPendingInvite(ctx, userID)
if err != nil {
return stacktrace.Propagate(err, "")
}
} else if *user.FamilyAdminID != userID {
logger.Info("user is part of family as member/child, leaving family")
err = c.LeaveFamily(ctx, userID)
if err != nil {
return stacktrace.Propagate(err, "")
}
} else {
logger.Info("user is a family admin, revoking invites & removing members")
members, err := c.FetchMembersForAdminID(ctx, userID)
if err != nil {
return stacktrace.Propagate(err, "")
}
for _, member := range members.Members {
if member.IsAdmin {
continue
} else if member.Status == ente.ACCEPTED {
logger.Info(fmt.Sprintf("removing memeber_id %d", member.MemberUserID))
err = c.RemoveMember(ctx, userID, member.ID)
if err != nil {
return stacktrace.Propagate(err, "")
}
} else if member.Status == ente.INVITED {
logger.Info(fmt.Sprintf("revoking invite member_id %d", member.MemberUserID))
err = c.RevokeInvite(ctx, userID, member.ID)
if err != nil {
return stacktrace.Propagate(err, "")
}
} else {
logger.WithField("member", member).Error("unxpected state during account deletion")
}
}
}
return nil
}