user_details.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. package user
  2. import (
  3. "github.com/ente-io/museum/ente"
  4. "github.com/ente-io/museum/ente/details"
  5. bonus "github.com/ente-io/museum/ente/storagebonus"
  6. "github.com/ente-io/museum/pkg/utils/auth"
  7. "github.com/ente-io/museum/pkg/utils/recover"
  8. "github.com/ente-io/museum/pkg/utils/time"
  9. "github.com/ente-io/stacktrace"
  10. "github.com/gin-gonic/gin"
  11. "golang.org/x/sync/errgroup"
  12. )
  13. func (c *UserController) GetDetails(ctx *gin.Context) (details.UserDetailsResponse, error) {
  14. enteApp := ctx.MustGet("app").(ente.App)
  15. userID := auth.GetUserID(ctx.Request.Header)
  16. user, err := c.UserRepo.Get(userID)
  17. if err != nil {
  18. return details.UserDetailsResponse{}, stacktrace.Propagate(err, "")
  19. }
  20. usage, err := c.FileRepo.GetUsage(userID)
  21. if err != nil {
  22. return details.UserDetailsResponse{}, stacktrace.Propagate(err, "")
  23. }
  24. fileCount, err := c.FileRepo.GetFileCountForUser(userID, enteApp)
  25. if err != nil {
  26. return details.UserDetailsResponse{}, stacktrace.Propagate(err, "")
  27. }
  28. sharedCollectionsCount, err := c.CollectionRepo.GetSharedCollectionsCount(userID)
  29. if err != nil {
  30. return details.UserDetailsResponse{}, stacktrace.Propagate(err, "")
  31. }
  32. subscription, err := c.BillingController.GetSubscription(ctx, userID)
  33. if err != nil {
  34. return details.UserDetailsResponse{}, stacktrace.Propagate(err, "")
  35. }
  36. return details.UserDetailsResponse{
  37. Email: user.Email,
  38. Usage: usage,
  39. FileCount: &fileCount,
  40. SharedCollectionsCount: &sharedCollectionsCount,
  41. Subscription: subscription,
  42. }, nil
  43. }
  44. func (c *UserController) getUserFileCountWithCache(userID int64, app ente.App) (int64, error) {
  45. // Check if the value is present in the cache
  46. if count, ok := c.UserCache.GetFileCount(userID, app); ok {
  47. // Cache hit, update the cache asynchronously
  48. go func() {
  49. _, _ = c.getUserCountAndUpdateCache(userID, app)
  50. }()
  51. return count, nil
  52. }
  53. return c.getUserCountAndUpdateCache(userID, app)
  54. }
  55. func (c *UserController) getUserCountAndUpdateCache(userID int64, app ente.App) (int64, error) {
  56. count, err := c.FileRepo.GetFileCountForUser(userID, app)
  57. if err != nil {
  58. return 0, stacktrace.Propagate(err, "")
  59. }
  60. c.UserCache.SetFileCount(userID, count, app)
  61. return count, nil
  62. }
  63. func (c *UserController) GetDetailsV2(ctx *gin.Context, userID int64, fetchMemoryCount bool, app ente.App) (details.UserDetailsResponse, error) {
  64. g := new(errgroup.Group)
  65. var user *ente.User
  66. var familyData *ente.FamilyMemberResponse
  67. var subscription *ente.Subscription
  68. var canDisableEmailMFA bool
  69. var fileCount, sharedCollectionCount, usage int64
  70. var bonus *bonus.ActiveStorageBonus
  71. g.Go(func() error {
  72. resp, err := c.UserRepo.Get(userID)
  73. if err != nil {
  74. return stacktrace.Propagate(err, "failed to get user")
  75. }
  76. user = &resp
  77. bonusUserId := userID
  78. if user.FamilyAdminID != nil {
  79. bonusUserId = *user.FamilyAdminID
  80. familyDataResp, familyErr := c.FamilyController.FetchMembersForAdminID(ctx, *user.FamilyAdminID)
  81. if familyErr != nil {
  82. return stacktrace.Propagate(familyErr, "")
  83. }
  84. familyData = &familyDataResp
  85. }
  86. bonusValue, bonusErr := c.UserCacheController.GetActiveStorageBonus(ctx, bonusUserId)
  87. if bonusErr != nil {
  88. return stacktrace.Propagate(bonusErr, "failed to fetch storage bonus")
  89. }
  90. bonus = bonusValue
  91. return nil
  92. })
  93. g.Go(func() error {
  94. subResp, err := c.BillingController.GetSubscription(ctx, userID)
  95. if err != nil {
  96. return stacktrace.Propagate(err, "")
  97. }
  98. subscription = &subResp
  99. return nil
  100. })
  101. g.Go(func() error {
  102. isSRPSetupDone, err := c.UserAuthRepo.IsSRPSetupDone(ctx, userID)
  103. if err != nil {
  104. return stacktrace.Propagate(err, "")
  105. }
  106. canDisableEmailMFA = isSRPSetupDone
  107. return nil
  108. })
  109. g.Go(func() error {
  110. return recover.Int64ToInt64RecoverWrapper(userID, c.FileRepo.GetUsage, &usage)
  111. })
  112. if fetchMemoryCount {
  113. g.Go(func() error {
  114. fCount, err := c.getUserFileCountWithCache(userID, app)
  115. if err == nil {
  116. fileCount = fCount
  117. }
  118. return err
  119. })
  120. }
  121. // g.Wait waits for all goroutines to complete
  122. // and returns the first non-nil error returned
  123. // by one of the goroutines.
  124. if err := g.Wait(); err != nil {
  125. return details.UserDetailsResponse{}, stacktrace.Propagate(err, "")
  126. }
  127. var planStoreForBonusComputation = subscription.Storage
  128. if subscription.ExpiryTime < time.Microseconds() {
  129. planStoreForBonusComputation = 0
  130. }
  131. if familyData != nil {
  132. if familyData.ExpiryTime < time.Microseconds() {
  133. familyData.Storage = 0
  134. } else {
  135. planStoreForBonusComputation = familyData.Storage
  136. }
  137. }
  138. storageBonus := bonus.GetUsableBonus(planStoreForBonusComputation)
  139. var result = details.UserDetailsResponse{
  140. Email: user.Email,
  141. FamilyData: familyData,
  142. Subscription: *subscription,
  143. Usage: usage,
  144. StorageBonus: storageBonus,
  145. ProfileData: &ente.ProfileData{
  146. CanDisableEmailMFA: canDisableEmailMFA,
  147. IsEmailMFAEnabled: *user.IsEmailMFAEnabled,
  148. IsTwoFactorEnabled: *user.IsTwoFactorEnabled,
  149. },
  150. BonusData: bonus,
  151. }
  152. if fetchMemoryCount {
  153. result.FileCount = &fileCount
  154. // Note: SharedCollectionsCount is deprecated. Returning default value as 0
  155. result.SharedCollectionsCount = &sharedCollectionCount
  156. }
  157. return result, nil
  158. }