Merge pull request #13 from Shchoholiev/bug/SA-143-Fix-data-retrieval-to-return-not-deleted-records

Bug fixed
This commit is contained in:
Mykhailo Bilodid 2023-11-18 01:53:04 +02:00 committed by GitHub
commit 7c7cc4f6b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 120 additions and 24 deletions

View File

@ -116,7 +116,7 @@ public class UserManager : ServiceBase, IUserManager
.GetOneAsync(r =>
r.Token == tokensModel.RefreshToken
&& r.CreatedById == userId
&& r.IsDeleted == false, cancellationToken);
, cancellationToken);
if (refreshTokenModel == null || refreshTokenModel.ExpiryDateUTC < DateTime.UtcNow)
{
throw new SecurityTokenExpiredException();
@ -310,7 +310,7 @@ public class UserManager : ServiceBase, IUserManager
private async Task CheckAndUpgradeToUserAsync(User user, CancellationToken cancellationToken)
{
if (user.Roles.Any(x => x.Name == "Guest") && !user.Roles.Any(x => x.Name == "User"))
if (user.Roles.Any(x => x.Name == "Guest" && x.IsDeleted == false) && !user.Roles.Any(x => x.Name == "User" && x.IsDeleted == false))
{
if (!string.IsNullOrEmpty(user.PasswordHash) && (!string.IsNullOrEmpty(user.Email) || !string.IsNullOrEmpty(user.Phone)))
{

View File

@ -73,7 +73,8 @@ public class WishlistsService : IWishlistsService
var wishlist = await TryGetPersonalWishlist(wishlistObjectId, cancellationToken);
var firstUserMessage = (await _messagesRepository.GetPageAsync(1, 1, x => x.WishlistId == wishlistObjectId && x.Role == MessageRoles.User.ToString(), cancellationToken)).First();
var firstUserMessage =
(await _messagesRepository.GetPageAsync(1, 1, x => x.WishlistId == wishlistObjectId && x.Role == MessageRoles.User.ToString(), cancellationToken)).First();
var chatCompletionRequest = new ChatCompletionRequest
{

View File

@ -3,6 +3,7 @@ using MongoDB.Driver;
using ShoppingAssistantApi.Application.IRepositories;
using ShoppingAssistantApi.Domain.Common;
using ShoppingAssistantApi.Persistance.Database;
using System;
using System.Linq.Expressions;
namespace ShoppingAssistantApi.Persistance.Repositories;
@ -21,12 +22,13 @@ public abstract class BaseRepository<TEntity> : IBaseRepository<TEntity> where T
public async Task<TEntity> GetOneAsync(ObjectId id, CancellationToken cancellationToken)
{
return await this._collection.Find(x => x.Id == id).FirstOrDefaultAsync(cancellationToken);
return await this._collection.Find(x => x.Id == id && x.IsDeleted == false).FirstOrDefaultAsync(cancellationToken);
}
public async Task<TEntity> GetOneAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
{
return await this._collection.Find(predicate).FirstOrDefaultAsync(cancellationToken);
return await this._collection.Find(Builders<TEntity>.Filter.Where(predicate) & Builders<TEntity>.Filter.Where(x => !x.IsDeleted))
.FirstOrDefaultAsync(cancellationToken);
}
public async Task<TEntity> AddAsync(TEntity entity, CancellationToken cancellationToken)
@ -37,7 +39,7 @@ public abstract class BaseRepository<TEntity> : IBaseRepository<TEntity> where T
public async Task<List<TEntity>> GetPageAsync(int pageNumber, int pageSize, CancellationToken cancellationToken)
{
return await this._collection.Find(Builders<TEntity>.Filter.Empty)
return await this._collection.Find(Builders<TEntity>.Filter.Where(x => !x.IsDeleted))
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
.ToListAsync(cancellationToken);
@ -45,7 +47,7 @@ public abstract class BaseRepository<TEntity> : IBaseRepository<TEntity> where T
public async Task<List<TEntity>> GetPageAsync(int pageNumber, int pageSize, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
{
return await this._collection.Find(predicate)
return await this._collection.Find(Builders<TEntity>.Filter.Where(predicate) & Builders<TEntity>.Filter.Where(x => !x.IsDeleted))
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)
.ToListAsync(cancellationToken);
@ -53,17 +55,18 @@ public abstract class BaseRepository<TEntity> : IBaseRepository<TEntity> where T
public async Task<int> GetTotalCountAsync()
{
return (int)(await this._collection.EstimatedDocumentCountAsync());
var filter = Builders<TEntity>.Filter.Eq("IsDeleted", false);
return (int)(await this._collection.CountDocumentsAsync(x => !x.IsDeleted));
}
public async Task<int> GetCountAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
{
return (int)(await this._collection.CountDocumentsAsync(predicate, cancellationToken: cancellationToken));
return (int)(await this._collection.CountDocumentsAsync(Builders<TEntity>.Filter.Where(predicate) & Builders<TEntity>.Filter.Where(x => !x.IsDeleted), cancellationToken: cancellationToken));
}
public async Task<bool> ExistsAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
{
return await this._collection.Find(predicate).AnyAsync(cancellationToken);
return await this._collection.Find(Builders<TEntity>.Filter.Where(predicate) & Builders<TEntity>.Filter.Where(x => !x.IsDeleted)).AnyAsync(cancellationToken);
}
public async Task<TEntity> DeleteAsync(TEntity entity, CancellationToken cancellationToken)

View File

@ -12,7 +12,7 @@ public class MessagesRepository : BaseRepository<Message>, IMessagesRepository
public async Task<List<Message>> GetPageStartingFromEndAsync(int pageNumber, int pageSize, Expression<Func<Message, bool>> predicate, CancellationToken cancellationToken)
{
return await _collection.Find(predicate)
return await _collection.Find(Builders<Message>.Filter.Where(predicate) & Builders<Message>.Filter.Where(x => !x.IsDeleted))
.SortByDescending(x => x.CreatedDateUtc)
.Skip((pageNumber - 1) * pageSize)
.Limit(pageSize)

View File

@ -13,11 +13,11 @@ public class RolesRepository : BaseRepository<Role>, IRolesRepository
public async Task<Role> GetRoleAsync(ObjectId id, CancellationToken cancellationToken)
{
return await (await this._collection.FindAsync(x => x.Id == id)).FirstOrDefaultAsync(cancellationToken);
return await (await this._collection.FindAsync(x => x.Id == id && x.IsDeleted == false)).FirstOrDefaultAsync(cancellationToken);
}
public async Task<Role> GetRoleAsync(Expression<Func<Role, bool>> predicate, CancellationToken cancellationToken)
{
return await (await this._collection.FindAsync(predicate)).FirstOrDefaultAsync(cancellationToken);
return await (await this._collection.FindAsync(Builders<Role>.Filter.Where(predicate) & Builders<Role>.Filter.Where(x => !x.IsDeleted))).FirstOrDefaultAsync(cancellationToken);
}
}

View File

@ -14,12 +14,12 @@ public class UsersRepository : BaseRepository<User>, IUsersRepository
public async Task<User> GetUserAsync(ObjectId id, CancellationToken cancellationToken)
{
return await (await this._collection.FindAsync(x => x.Id == id)).FirstOrDefaultAsync(cancellationToken);
return await (await this._collection.FindAsync(x => x.Id == id && x.IsDeleted == false)).FirstOrDefaultAsync(cancellationToken);
}
public async Task<User> GetUserAsync(Expression<Func<User, bool>> predicate, CancellationToken cancellationToken)
{
return await (await this._collection.FindAsync(predicate)).FirstOrDefaultAsync(cancellationToken);
return await (await this._collection.FindAsync(Builders<User>.Filter.Where(predicate) & Builders<User>.Filter.Where(x => !x.IsDeleted))).FirstOrDefaultAsync(cancellationToken);
}
public async Task<User> UpdateUserAsync(User user, CancellationToken cancellationToken)
@ -39,6 +39,6 @@ public class UsersRepository : BaseRepository<User>, IUsersRepository
};
return await this._collection.FindOneAndUpdateAsync(
Builders<User>.Filter.Eq(u => u.Id, user.Id), updateDefinition, options, cancellationToken);
Builders<User>.Filter.Eq(u => u.Id, user.Id) & Builders<User>.Filter.Where(x => !x.IsDeleted), updateDefinition, options, cancellationToken);
}
}

View File

@ -13,13 +13,13 @@ public class WishlistsRepository : BaseRepository<Wishlist>, IWishlistsRepositor
public async Task<Wishlist> GetWishlistAsync(Expression<Func<Wishlist, bool>> predicate, CancellationToken cancellationToken)
{
return await (await _collection.FindAsync(predicate)).FirstOrDefaultAsync(cancellationToken);
return await (await _collection.FindAsync(Builders<Wishlist>.Filter.Where(predicate) & Builders<Wishlist>.Filter.Where(x => !x.IsDeleted))).FirstOrDefaultAsync(cancellationToken);
}
public async Task<Wishlist> UpdateWishlistNameAsync(ObjectId wishlistId, string newName,
ObjectId updatedById, CancellationToken cancellationToken)
{
var filterDefinition = Builders<Wishlist>.Filter.Eq(w => w.Id, wishlistId);
var filterDefinition = Builders<Wishlist>.Filter.Eq(w => w.Id, wishlistId) & Builders<Wishlist>.Filter.Where(x => !x.IsDeleted);
var updateDefinition = Builders<Wishlist>.Update
.Set(w => w.Name, newName)

View File

@ -109,6 +109,7 @@ public class DbInitializer
var wishlistId2 = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab");
var wishlistId3 = ObjectId.Parse("ab7c8c2d9edf39abcd1ef9ab");
var wishlistId4 = ObjectId.Parse("ab8c8c2d9edf39abcd1ef9ab");
var wishlistId5 = ObjectId.Parse("65575253dbe88a3c118e1ca2");
var wishlists = new Wishlist[]
{
@ -121,6 +122,14 @@ public class DbInitializer
CreatedDateUtc = DateTime.UtcNow
},
new Wishlist
{
Id = wishlistId5,
Name = "Gaming PC",
Type = WishlistTypes.Product.ToString(),
CreatedById = user1.Id,
CreatedDateUtc = DateTime.UtcNow
},
new Wishlist
{
Id = wishlistId2,
Name = "Generic Wishlist Name",
@ -162,6 +171,8 @@ public class DbInitializer
var wishlistId2 = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab");
var wishlistId3 = ObjectId.Parse("ab7c8c2d9edf39abcd1ef9ab");
var wishlistId4 = ObjectId.Parse("ab8c8c2d9edf39abcd1ef9ab");
var wishlistId5 = ObjectId.Parse("65575253dbe88a3c118e1ca2");
var messages = new Message[]
{
@ -211,6 +222,51 @@ public class DbInitializer
CreatedDateUtc = DateTime.UtcNow.AddSeconds(50)
},
new Message
{
Text = "Message 1",
Role = MessageRoles.User.ToString(),
WishlistId = wishlistId5,
CreatedById = user1.Id,
CreatedDateUtc = DateTime.UtcNow
},
new Message
{
Text = "Message 2",
Role = MessageRoles.Application.ToString(),
WishlistId = wishlistId5,
CreatedDateUtc = DateTime.UtcNow.AddSeconds(5)
},
new Message
{
Text = "Message 3",
Role = MessageRoles.User.ToString(),
WishlistId = wishlistId5,
CreatedById = user1.Id,
CreatedDateUtc = DateTime.UtcNow.AddSeconds(20)
},
new Message
{
Text = "Message 4",
Role = MessageRoles.Application.ToString(),
WishlistId = wishlistId5,
CreatedDateUtc = DateTime.UtcNow.AddSeconds(25)
},
new Message
{
Text = "Message 5",
Role = MessageRoles.User.ToString(),
WishlistId = wishlistId5,
CreatedById = user1.Id,
CreatedDateUtc = DateTime.UtcNow.AddSeconds(45)
},
new Message
{
Text = "Message 6",
Role = MessageRoles.Application.ToString(),
WishlistId = wishlistId5,
CreatedDateUtc = DateTime.UtcNow.AddSeconds(50)
},
new Message
{
Text = "Prompt",
Role = MessageRoles.User.ToString(),
@ -249,6 +305,7 @@ public class DbInitializer
var wishlistId1 = ObjectId.Parse("ab79cde6f69abcd3efab65cd");
var wishlistId2 = ObjectId.Parse("ab6c2c2d9edf39abcd1ef9ab");
var wishlistId3 = ObjectId.Parse("65575253dbe88a3c118e1ca2");
var products = new Product[]
{
@ -285,6 +342,40 @@ public class DbInitializer
WishlistId = wishlistId1,
CreatedById = user1.Id,
CreatedDateUtc = DateTime.UtcNow
},
new Product
{
Name = "AMD Ryzen 5 5600G 6-Core 12-Thread Unlocked Desktop Processor with Radeon Graphics",
Description = "Features best-in-class graphics performance in a desktop processor for smooth 1080p gaming, no graphics card required",
Rating = 4.8,
Price = 120,
Url = "https://a.co/d/5ceuIrq",
ImagesUrls = new string[]
{
"https://m.media-amazon.com/images/I/51f2hkWjTlL._AC_SL1200_.jpg",
"https://m.media-amazon.com/images/I/51iji7Gel-L._AC_SL1200_.jpg"
},
WasOpened = false,
WishlistId = wishlistId3,
CreatedById = user1.Id,
CreatedDateUtc = DateTime.UtcNow
},
new Product
{
Name = "Samsung 970 EVO Plus SSD 2TB NVMe M.2 Internal Solid State Hard Drive, V-NAND Technology, Storage and Memory Expansion for Gaming, Graphics w/ Heat Control, Max Speed, MZ-V7S2T0B/AM ",
Description = "7 Year Limited Warranty: The 970 EVO Plus provides up to 1200 TBW (Terabytes Written) with 5-years of protection for exceptional endurance powered by the latest V-NAND technology and Samsung's reputation for quality ",
Rating = 4.8,
Price = 153,
Url = "https://a.co/d/gxnuqs1",
ImagesUrls = new string[]
{
"https://m.media-amazon.com/images/I/51Brl+iYtvL._AC_SL1001_.jpg",
"https://m.media-amazon.com/images/I/51GOfLlVwoL._AC_SL1001_.jpg"
},
WasOpened = false,
WishlistId = wishlistId3,
CreatedById = user1.Id,
CreatedDateUtc = DateTime.UtcNow
},
};

View File

@ -26,6 +26,7 @@ public class WishlistsTests : TestsBase
private const string TestingValidWishlistId = "ab79cde6f69abcd3efab65cd";
private const string TestingValidWishlistId2 = "65575253dbe88a3c118e1ca2";
public WishlistsTests(TestingFactory<Program> factory)
: base(factory)
@ -178,7 +179,7 @@ public class WishlistsTests : TestsBase
}",
variables = new
{
wishlistId = TestingValidWishlistId
wishlistId = TestingValidWishlistId2
}
};
@ -246,7 +247,7 @@ public class WishlistsTests : TestsBase
}",
variables = new
{
wishlistId = TestingValidWishlistId,
wishlistId = TestingValidWishlistId2,
pageNumber = 1,
pageSize = 2
}
@ -823,7 +824,7 @@ public class WishlistsTests : TestsBase
}",
variables = new
{
wishlistId = TestingValidWishlistId,
wishlistId = TestingValidWishlistId2,
pageNumber = 100,
pageSize = 2
}
@ -878,7 +879,7 @@ public class WishlistsTests : TestsBase
query = "query productsPageFromPersonalWishlist($wishlistId: String!, $pageNumber: Int!, $pageSize: Int!) { productsPageFromPersonalWishlist (wishlistId: $wishlistId, pageNumber: $pageNumber, pageSize: $pageSize) { hasNextPage, hasPreviousPage, items { id, url, name, description, rating, imagesUrls, wasOpened, wishlistId }, pageNumber, pageSize, totalItems, totalPages } }",
variables = new
{
wishlistId = TestingValidWishlistId,
wishlistId = TestingValidWishlistId2,
pageNumber = 1,
pageSize = 100
}
@ -890,7 +891,7 @@ public class WishlistsTests : TestsBase
Assert.NotNull(pagedList);
Assert.Equal("Samsung 970 EVO Plus SSD 2TB NVMe M.2 Internal Solid State Hard Drive, V-NAND Technology, Storage and Memory Expansion for Gaming, Graphics w/ Heat Control, Max Speed, MZ-V7S2T0B/AM ", pagedList.Items.ToList()[1].Name);
Assert.Equal(TestingValidWishlistId, pagedList.Items.ToList()[1].WishlistId);
Assert.Equal(TestingValidWishlistId2, pagedList.Items.ToList()[1].WishlistId);
}
[Fact]