referral.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. package storagebonus
  2. import (
  3. "database/sql"
  4. "errors"
  5. "github.com/ente-io/museum/pkg/utils/random"
  6. "github.com/ente-io/museum/ente"
  7. entity "github.com/ente-io/museum/ente/storagebonus"
  8. "github.com/ente-io/museum/pkg/controller/email"
  9. "github.com/ente-io/museum/pkg/controller/lock"
  10. "github.com/ente-io/museum/pkg/repo"
  11. "github.com/ente-io/museum/pkg/repo/storagebonus"
  12. "github.com/ente-io/museum/pkg/utils/auth"
  13. enteTime "github.com/ente-io/museum/pkg/utils/time"
  14. "github.com/ente-io/stacktrace"
  15. "github.com/gin-gonic/gin"
  16. )
  17. const (
  18. codeLength = 6
  19. referralAmountInGb = 10
  20. maxClaimableReferralAmount = 2000
  21. numOfDaysToClaimReferral = 32
  22. defaultPlanType = entity.TenGbOnUpgrade
  23. )
  24. // Controller exposes functions to interact with family module
  25. type Controller struct {
  26. UserRepo *repo.UserRepository
  27. StorageBonus *storagebonus.Repository
  28. LockController *lock.LockController
  29. CronRunning bool
  30. EmailNotificationController *email.EmailNotificationController
  31. }
  32. func (c *Controller) GetUserReferralView(ctx *gin.Context) (*entity.GetUserReferralView, error) {
  33. // Get the user id from the context
  34. userID := auth.GetUserID(ctx.Request.Header)
  35. // Use goroutines to fetch UserRepo.Get, HasAppliedReferral
  36. user, err := c.UserRepo.Get(userID)
  37. if err != nil {
  38. return nil, stacktrace.Propagate(err, "failed to get user")
  39. }
  40. appliedReferral, err := c.StorageBonus.HasAppliedReferral(ctx, userID)
  41. if err != nil {
  42. return nil, stacktrace.Propagate(err, "")
  43. }
  44. isFamilyMember := user.FamilyAdminID != nil && *user.FamilyAdminID != userID
  45. enableApplyCode := !appliedReferral && user.CreationTime > enteTime.MicrosecondBeforeDays(numOfDaysToClaimReferral) && !isFamilyMember
  46. // Get the referral code for the user or family admin
  47. codeUser := userID
  48. if isFamilyMember {
  49. codeUser = *user.FamilyAdminID
  50. }
  51. referralCode, err2 := c.GetOrCreateReferralCode(ctx, codeUser)
  52. if err2 != nil {
  53. return nil, stacktrace.Propagate(err2, "failed to get or create referral code")
  54. }
  55. storageClaimed, err2 := c.GetActiveReferralBonusValue(ctx, codeUser)
  56. if err2 != nil {
  57. return nil, stacktrace.Propagate(err2, "failed to get storage claimed")
  58. }
  59. return &entity.GetUserReferralView{
  60. PlanInfo: entity.PlanInfo{
  61. IsEnabled: true,
  62. PlanType: defaultPlanType,
  63. StorageInGB: referralAmountInGb,
  64. MaxClaimableStorageInGB: maxClaimableReferralAmount,
  65. },
  66. Code: referralCode,
  67. EnableApplyCode: enableApplyCode,
  68. IsFamilyMember: isFamilyMember,
  69. HasAppliedCode: appliedReferral,
  70. ClaimedStorage: *storageClaimed,
  71. }, nil
  72. }
  73. func (c *Controller) ApplyReferralCode(ctx *gin.Context, code string) error {
  74. // Get user id from the context
  75. userID := auth.GetUserID(ctx.Request.Header)
  76. user, err := c.UserRepo.Get(userID)
  77. if err != nil {
  78. return stacktrace.Propagate(err, "failed to get user")
  79. }
  80. codeOwnerID, err := c.StorageBonus.GetUserIDByCode(ctx, code)
  81. if err != nil {
  82. return stacktrace.Propagate(err, "failed to get user id by code")
  83. }
  84. // Verify that the codeOwnerID is not deleted yet
  85. _, err = c.UserRepo.Get(*codeOwnerID)
  86. if err != nil {
  87. if errors.Is(err, ente.ErrUserDeleted) {
  88. return stacktrace.Propagate(entity.InvalidCodeErr, "code belongs to deleted user")
  89. }
  90. return stacktrace.Propagate(err, "failed to get user")
  91. }
  92. if user.CreationTime < enteTime.MicrosecondBeforeDays(numOfDaysToClaimReferral) {
  93. return stacktrace.Propagate(entity.CanNotApplyCodeErr, "account is too old to apply code")
  94. } else if user.FamilyAdminID != nil && userID != *user.FamilyAdminID {
  95. return stacktrace.Propagate(entity.CanNotApplyCodeErr, "user is member of a family plan")
  96. }
  97. err = c.StorageBonus.TrackReferralAndInviteeBonus(ctx, userID, *codeOwnerID, defaultPlanType)
  98. if err != nil {
  99. return stacktrace.Propagate(err, "failed to apply code")
  100. }
  101. return nil
  102. }
  103. func (c *Controller) GetOrCreateReferralCode(ctx *gin.Context, userID int64) (*string, error) {
  104. referralCode, err := c.StorageBonus.GetCode(ctx, userID)
  105. if err != nil {
  106. if !errors.Is(err, sql.ErrNoRows) {
  107. return nil, stacktrace.Propagate(err, "failed to get storagebonus code")
  108. }
  109. code, err := random.GenerateAlphaNumString(codeLength)
  110. if err != nil {
  111. return nil, stacktrace.Propagate(err, "")
  112. }
  113. err = c.StorageBonus.InsertCode(ctx, userID, code)
  114. if err != nil {
  115. return nil, stacktrace.Propagate(err, "failed to insert storagebonus code")
  116. }
  117. referralCode = &code
  118. }
  119. return referralCode, nil
  120. }