diff --git a/Notesnook.API/Helpers/StorageHelper.cs b/Notesnook.API/Helpers/StorageHelper.cs index 4ea49bf..1f0aee0 100644 --- a/Notesnook.API/Helpers/StorageHelper.cs +++ b/Notesnook.API/Helpers/StorageHelper.cs @@ -52,6 +52,17 @@ namespace Notesnook.API.Helpers return fileSize > maxFileSize; } + public static Limit RolloverStorageLimit(Limit? limit) + { + var updatedAt = DateTimeOffset.FromUnixTimeMilliseconds(limit?.UpdatedAt ?? 0); + if (limit == null || DateTimeOffset.UtcNow.Year > updatedAt.Year || DateTimeOffset.UtcNow.Month > updatedAt.Month) + { + limit = new Limit { UpdatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), Value = 0 }; + return limit; + } + return limit; + } + private static readonly string[] sizes = ["B", "KB", "MB", "GB", "TB"]; public static string FormatBytes(long size) { diff --git a/Notesnook.API/Models/UserSettings.cs b/Notesnook.API/Models/UserSettings.cs index e6cfaa6..ef817a6 100644 --- a/Notesnook.API/Models/UserSettings.cs +++ b/Notesnook.API/Models/UserSettings.cs @@ -17,6 +17,7 @@ You should have received a copy of the Affero GNU General Public License along with this program. If not, see . */ +using System; using MongoDB.Bson; using MongoDB.Bson.Serialization.Attributes; using Notesnook.API.Interfaces; @@ -25,8 +26,21 @@ namespace Notesnook.API.Models { public class Limit { - public long Value { get; set; } - public long UpdatedAt { get; set; } + private long _value = 0; + public long Value + { + get => _value; + set + { + _value = value; + UpdatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); + } + } + public long UpdatedAt + { + get; + set; + } } public class UserSettings diff --git a/Notesnook.API/Services/S3Service.cs b/Notesnook.API/Services/S3Service.cs index 7d657c1..a9e6b30 100644 --- a/Notesnook.API/Services/S3Service.cs +++ b/Notesnook.API/Services/S3Service.cs @@ -239,7 +239,7 @@ namespace Notesnook.API.Services await this.AbortMultipartUploadAsync(userId, uploadRequest.Key, uploadRequest.UploadId); throw new Exception("User settings not found."); } - userSettings.StorageLimit ??= new Limit { Value = 0, UpdatedAt = 0 }; + userSettings.StorageLimit ??= StorageHelper.RolloverStorageLimit(userSettings.StorageLimit); if (!Constants.IS_SELF_HOSTED) { @@ -268,8 +268,11 @@ namespace Notesnook.API.Services if (!Constants.IS_SELF_HOSTED) { - userSettings.StorageLimit.UpdatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); await Repositories.UsersSettings.UpsertAsync(userSettings, (u) => u.UserId == userId); + await Repositories.UsersSettings.Collection.UpdateOneAsync( + Builders.Filter.Eq(u => u.UserId, userId), + Builders.Update.Set(u => u.StorageLimit, userSettings.StorageLimit) + ); } } diff --git a/Notesnook.API/Services/UserService.cs b/Notesnook.API/Services/UserService.cs index 60f8da3..5d55bc7 100644 --- a/Notesnook.API/Services/UserService.cs +++ b/Notesnook.API/Services/UserService.cs @@ -24,6 +24,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; +using MongoDB.Driver; using Notesnook.API.Helpers; using Notesnook.API.Interfaces; using Notesnook.API.Models; @@ -115,10 +116,14 @@ namespace Notesnook.API.Services var userSettings = await Repositories.UsersSettings.FindOneAsync((u) => u.UserId == user.UserId) ?? throw new Exception("User settings not found."); // reset user's attachment limit every month - if (userSettings.StorageLimit == null || DateTimeOffset.UtcNow.Month > DateTimeOffset.FromUnixTimeMilliseconds(userSettings.StorageLimit.UpdatedAt).Month) + var limit = StorageHelper.RolloverStorageLimit(userSettings.StorageLimit); + if (userSettings.StorageLimit == null || limit.UpdatedAt != userSettings.StorageLimit?.UpdatedAt) { - userSettings.StorageLimit ??= new Limit { UpdatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), Value = 0 }; - await Repositories.UsersSettings.UpsertAsync(userSettings, (u) => u.UserId == user.UserId); + userSettings.StorageLimit = limit; + await Repositories.UsersSettings.Collection.UpdateOneAsync( + Builders.Filter.Eq(u => u.UserId, user.UserId), + Builders.Update.Set(u => u.StorageLimit, userSettings.StorageLimit) + ); } return new UserResponse