diff --git a/RelationshipAnalysis.Integration.Test/Controllers/CategoryControllerTests.cs b/RelationshipAnalysis.Integration.Test/Controllers/CategoryControllerTests.cs new file mode 100644 index 0000000..ab27699 --- /dev/null +++ b/RelationshipAnalysis.Integration.Test/Controllers/CategoryControllerTests.cs @@ -0,0 +1,167 @@ +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Text.Json; +using System.Text; +using Microsoft.Extensions.Options; +using Moq; +using Newtonsoft.Json; +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Dto.Category; +using RelationshipAnalysis.Models.Auth; +using RelationshipAnalysis.Services.UserPanelServices.Abstraction.AuthServices; +using RelationshipAnalysis.Settings.JWT; +using JsonSerializer = System.Text.Json.JsonSerializer; + +namespace RelationshipAnalysis.Integration.Test.Controllers; + +public class CategoryControllerTests : IClassFixture> +{ + private readonly HttpClient _client; + + public CategoryControllerTests(CustomWebApplicationFactory factory) + { + _client = factory.CreateClient(); + } + + [Fact] + public async Task GetAllNodeCategories_ShouldReturnCorrectList_Whenever() + { + // Arrange + var expectedResult1 = "Person"; + var expectedResult2 = "Account"; + var request = new HttpRequestMessage(HttpMethod.Get, "/api/category/GetAllNodeCategories"); + var jwtSettings = new JwtSettings + { + Key = "kajbdiuhdqhpjQE89HBSDJIABFCIWSGF89GW3EJFBWEIUBCZNMXCJNLZDKNJKSNJKFBIGW3EASHHDUIASZGCUI", + ExpireMinutes = 60 + }; + Mock> mockJwtSettings = new(); + mockJwtSettings.Setup(m => m.Value).Returns(jwtSettings); + var user = new User() + { + Username = "Test", + UserRoles = new List() { new UserRole() { Role = new Role() { Name = "Admin" } } } + }; + var token = new JwtTokenGenerator(mockJwtSettings.Object).GenerateJwtToken(user); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + var response = await _client.SendAsync(request); + + // Assert + response.EnsureSuccessStatusCode(); + var responseData = await response.Content.ReadFromJsonAsync>(); + Assert.NotNull(responseData); + Assert.Contains(expectedResult1, responseData); + Assert.Contains(expectedResult2, responseData); + } + + [Fact] + public async Task GetAllEdgeCategories_ShouldReturnCorrectList_Whenever() + { + // Arrange + var expectedResult1 = "Transaction"; + var request = new HttpRequestMessage(HttpMethod.Get, "/api/category/GetAllEdgeCategories"); + var jwtSettings = new JwtSettings + { + Key = "kajbdiuhdqhpjQE89HBSDJIABFCIWSGF89GW3EJFBWEIUBCZNMXCJNLZDKNJKSNJKFBIGW3EASHHDUIASZGCUI", + ExpireMinutes = 60 + }; + Mock> mockJwtSettings = new(); + mockJwtSettings.Setup(m => m.Value).Returns(jwtSettings); + var user = new User() + { + Username = "Test", + UserRoles = new List() { new UserRole() { Role = new Role() { Name = "Admin" } } } + }; + var token = new JwtTokenGenerator(mockJwtSettings.Object).GenerateJwtToken(user); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + + // Act + var response = await _client.SendAsync(request); + + // Assert + response.EnsureSuccessStatusCode(); + var responseData = await response.Content.ReadFromJsonAsync>(); + Assert.NotNull(responseData); + Assert.Contains(expectedResult1, responseData); + } + + [Fact] + public async Task CreateNodeCategory_ShouldReturnCorrectList_Whenever() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Post, "/api/category/CreateNodeCategory"); + var jwtSettings = new JwtSettings + { + Key = "kajbdiuhdqhpjQE89HBSDJIABFCIWSGF89GW3EJFBWEIUBCZNMXCJNLZDKNJKSNJKFBIGW3EASHHDUIASZGCUI", + ExpireMinutes = 60 + }; + Mock> mockJwtSettings = new(); + mockJwtSettings.Setup(m => m.Value).Returns(jwtSettings); + var user = new User() + { + Username = "Test", + UserRoles = new List() { new UserRole() { Role = new Role() { Name = "Admin" } } } + }; + var token = new JwtTokenGenerator(mockJwtSettings.Object).GenerateJwtToken(user); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + + var dto = new CreateNodeCategoryDto() + { + NodeCategoryName = "NotExist" + }; + request.Content = new StringContent( + JsonSerializer.Serialize(dto), + Encoding.UTF8, + "application/json" + ); + + // Act + var response = await _client.SendAsync(request); + + // Assert + response.EnsureSuccessStatusCode(); + var responseData = await response.Content.ReadFromJsonAsync(); + Assert.NotNull(responseData); + } + + [Fact] + public async Task CreateEdgeCategory_ShouldReturnCorrectList_Whenever() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Post, "/api/category/CreateEdgeCategory"); + var jwtSettings = new JwtSettings + { + Key = "kajbdiuhdqhpjQE89HBSDJIABFCIWSGF89GW3EJFBWEIUBCZNMXCJNLZDKNJKSNJKFBIGW3EASHHDUIASZGCUI", + ExpireMinutes = 60 + }; + Mock> mockJwtSettings = new(); + mockJwtSettings.Setup(m => m.Value).Returns(jwtSettings); + var user = new User() + { + Username = "Test", + UserRoles = new List() { new UserRole() { Role = new Role() { Name = "Admin" } } } + }; + var token = new JwtTokenGenerator(mockJwtSettings.Object).GenerateJwtToken(user); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + + var dto = new CreateEdgeCategoryDto() + { + EdgeCategoryName = "NotExist" + }; + request.Content = new StringContent( + JsonSerializer.Serialize(dto), + Encoding.UTF8, + "application/json" + ); + + // Act + var response = await _client.SendAsync(request); + + // Assert + response.EnsureSuccessStatusCode(); + var responseData = await response.Content.ReadFromJsonAsync(); + Assert.NotNull(responseData); + } +} \ No newline at end of file diff --git a/RelationshipAnalysis.Integration.Test/Controllers/CustomWebApplicaionFactory.cs b/RelationshipAnalysis.Integration.Test/Controllers/CustomWebApplicaionFactory.cs index 19b84e1..30e3b4a 100644 --- a/RelationshipAnalysis.Integration.Test/Controllers/CustomWebApplicaionFactory.cs +++ b/RelationshipAnalysis.Integration.Test/Controllers/CustomWebApplicaionFactory.cs @@ -5,6 +5,7 @@ using RelationshipAnalysis.Context; using RelationshipAnalysis.Models; using RelationshipAnalysis.Models.Auth; +using RelationshipAnalysis.Models.Graph; namespace RelationshipAnalysis.Integration.Test.Controllers; @@ -71,5 +72,46 @@ private void SeedDatabase(ApplicationDbContext dbContext) dbContext.Users.Add(user); dbContext.Roles.Add(role); dbContext.SaveChanges(); + + var nodeCategory1 = new NodeCategory { NodeCategoryName = "Account" }; + var nodeCategory2 = new NodeCategory { NodeCategoryName = "Person" }; + + var node1 = new Node + { + NodeUniqueString = "Node1", + NodeCategory = nodeCategory1, + NodeCategoryId = nodeCategory1.NodeCategoryId + }; + + var node2 = new Node + { + NodeUniqueString = "Node2", + NodeCategory = nodeCategory2, + NodeCategoryId = nodeCategory2.NodeCategoryId + }; + + var edgeCategory = new EdgeCategory { EdgeCategoryName = "Transaction"}; + + + dbContext.NodeCategories.Add(nodeCategory1); + dbContext.NodeCategories.Add(nodeCategory2); + dbContext.Nodes.Add(node1); + dbContext.Nodes.Add(node2); + dbContext.EdgeCategories.Add(edgeCategory); + + + var edge = new Edge + { + EdgeSourceNodeId = node1.NodeId, + EdgeDestinationNodeId = node2.NodeId, + EdgeCategory = edgeCategory, + EdgeCategoryId = edgeCategory.EdgeCategoryId, + EdgeUniqueString = "Edge1" + }; + + dbContext.Edges.Add(edge); + + dbContext.SaveChangesAsync(); + } } \ No newline at end of file diff --git a/RelationshipAnalysis.Integration.Test/Controllers/GraphControllerTests.cs b/RelationshipAnalysis.Integration.Test/Controllers/GraphControllerTests.cs new file mode 100644 index 0000000..fc10355 --- /dev/null +++ b/RelationshipAnalysis.Integration.Test/Controllers/GraphControllerTests.cs @@ -0,0 +1,121 @@ +using System.Net.Http.Headers; +using System.Net.Http.Json; +using Microsoft.Extensions.Options; +using Moq; +using RelationshipAnalysis.Dto.Graph; +using RelationshipAnalysis.Models.Auth; +using RelationshipAnalysis.Models.Graph; +using RelationshipAnalysis.Services.UserPanelServices.Abstraction.AuthServices; +using RelationshipAnalysis.Settings.JWT; + +namespace RelationshipAnalysis.Integration.Test.Controllers; + +public class GraphControllerTests : IClassFixture> +{ + + private readonly HttpClient _client; + private readonly JwtSettings _jwtSettings; + + public GraphControllerTests(CustomWebApplicationFactory factory) + { + _client = factory.CreateClient(); + _jwtSettings = new JwtSettings + { + Key = "kajbdiuhdqhpjQE89HBSDJIABFCIWSGF89GW3EJFBWEIUBCZNMXCJNLZDKNJKSNJKFBIGW3EASHHDUIASZGCUI", + ExpireMinutes = 60 + }; + } + + [Fact] + public async Task GetGraph_ShouldReturnGraph_WhenUserIsAuthorized() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Get, "/api/graph/getgraph"); + Mock> mockJwtSettings = new(); + mockJwtSettings.Setup(m => m.Value).Returns(_jwtSettings); + var user = new User + { + Id = 1, + Username = "admin", + PasswordHash = "74b2c5bd3a8de69c8c7c643e8b5c49d6552dc636aeb0995aff6f01a1f661a979", + FirstName = "Admin", + LastName = "User", + Email = "admin@example.com", + UserRoles = new List() { new UserRole() { Role = new Role() { Name = "admin" } } } + + }; + + var token = new JwtTokenGenerator(mockJwtSettings.Object).GenerateJwtToken(user); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + + + var nodeCategory1 = new NodeCategory { NodeCategoryName = "Account" }; + var nodeCategory2 = new NodeCategory { NodeCategoryName = "Person" }; + + var node1 = new Node + { + NodeId = 1, + NodeUniqueString = "Node1", + NodeCategory = nodeCategory1, + NodeCategoryId = nodeCategory1.NodeCategoryId + }; + + var node2 = new Node + { + NodeId = 2, + NodeUniqueString = "Node2", + NodeCategory = nodeCategory2, + NodeCategoryId = nodeCategory2.NodeCategoryId + }; + + var edgeCategory = new EdgeCategory { EdgeCategoryName = "Transaction"}; + + + + var expectedNodes = new List() + { + new NodeDto() + { + id = node1.NodeId.ToString(), + label = $"{node1.NodeCategory.NodeCategoryName}/{node1.NodeUniqueString}" + }, + new NodeDto() + { + id = node2.NodeId.ToString(), + label = $"{node2.NodeCategory.NodeCategoryName}/{node2.NodeUniqueString}" + } + }; + + var edge = new Edge + { + EdgeId = 1, + EdgeSourceNodeId = node1.NodeId, + EdgeDestinationNodeId = node2.NodeId, + EdgeCategory = edgeCategory, + EdgeCategoryId = edgeCategory.EdgeCategoryId, + EdgeUniqueString = "Edge1" + }; + + + var expectedEdges = new List() + { + new EdgeDto() + { + id = edge.EdgeId.ToString(), + source = node1.NodeId.ToString(), + target = node2.NodeId.ToString() + } + }; + + + // Act + var response = await _client.SendAsync(request); + + // Assert + response.EnsureSuccessStatusCode(); + var responseData = await response.Content.ReadFromJsonAsync(); + Assert.Equivalent(responseData.nodes, expectedNodes); + Assert.Equivalent(responseData.edges, expectedEdges); + + } +} \ No newline at end of file diff --git a/RelationshipAnalysis.Test/Resources.Designer.cs b/RelationshipAnalysis.Test/Resources.Designer.cs index 067cd75..53f2d28 100644 --- a/RelationshipAnalysis.Test/Resources.Designer.cs +++ b/RelationshipAnalysis.Test/Resources.Designer.cs @@ -11,32 +11,46 @@ namespace RelationshipAnalysis.Test { using System; - [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [System.Diagnostics.DebuggerNonUserCodeAttribute()] - [System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { - private static System.Resources.ResourceManager resourceMan; + private static global::System.Resources.ResourceManager resourceMan; - private static System.Globalization.CultureInfo resourceCulture; + private static global::System.Globalization.CultureInfo resourceCulture; - [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - internal static System.Resources.ResourceManager ResourceManager { + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { get { - if (object.Equals(null, resourceMan)) { - System.Resources.ResourceManager temp = new System.Resources.ResourceManager("RelationshipAnalysis.Test.Resources", typeof(Resources).Assembly); + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RelationshipAnalysis.Test.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)] - internal static System.Globalization.CultureInfo Culture { + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } @@ -45,82 +59,202 @@ internal static System.Globalization.CultureInfo Culture { } } - internal static string UsernameExistsMessage { + /// + /// Looks up a localized string similar to You cant delete your account!. + /// + internal static string DeleteAccountAccessErrorMessage { get { - return ResourceManager.GetString("UsernameExistsMessage", resourceCulture); + return ResourceManager.GetString("DeleteAccountAccessErrorMessage", resourceCulture); } } + /// + /// Looks up a localized string similar to Chosen email already exists. + /// internal static string EmailExistsMessage { get { return ResourceManager.GetString("EmailExistsMessage", resourceCulture); } } - internal static string SuccessfulLogoutMessage { + /// + /// Looks up a localized string similar to Roles cant be empty!. + /// + internal static string EmptyRolesMessage { get { - return ResourceManager.GetString("SuccessfulLogoutMessage", resourceCulture); + return ResourceManager.GetString("EmptyRolesMessage", resourceCulture); } } + /// + /// Looks up a localized string similar to Password must contain one digit from 1 to 9, one lowercase letter, one uppercase letter, one special character, no space, and it must be 8-16 characters long.. + /// internal static string InvalidPasswordMessage { get { return ResourceManager.GetString("InvalidPasswordMessage", resourceCulture); } } - internal static string UserNotFoundMessage { + /// + /// Looks up a localized string similar to Roles are invalid!. + /// + internal static string InvalidRolesListMessage { get { - return ResourceManager.GetString("UserNotFoundMessage", resourceCulture); + return ResourceManager.GetString("InvalidRolesListMessage", resourceCulture); } } - internal static string WrongOldPasswordMessage { + /// + /// Looks up a localized string similar to Login Failed!. + /// + internal static string LoginFailedMessage { get { - return ResourceManager.GetString("WrongOldPasswordMessage", resourceCulture); + return ResourceManager.GetString("LoginFailedMessage", resourceCulture); } } - internal static string OldPasswordRequired { + /// + /// Looks up a localized string similar to New password is required. + /// + internal static string NewPasswordRequired { get { - return ResourceManager.GetString("OldPasswordRequired", resourceCulture); + return ResourceManager.GetString("NewPasswordRequired", resourceCulture); } } - internal static string NewPasswordRequired { + /// + /// Looks up a localized string similar to Category Name is not unique!. + /// + internal static string NotUniqueCategoryNameErrorMessage { get { - return ResourceManager.GetString("NewPasswordRequired", resourceCulture); + return ResourceManager.GetString("NotUniqueCategoryNameErrorMessage", resourceCulture); } } - internal static string UsernameRequired { + /// + /// Looks up a localized string similar to Input Dto can not be null!. + /// + internal static string NullDtoErrorMessage { get { - return ResourceManager.GetString("UsernameRequired", resourceCulture); + return ResourceManager.GetString("NullDtoErrorMessage", resourceCulture); } } + /// + /// Looks up a localized string similar to Old password is required. + /// + internal static string OldPasswordRequired { + get { + return ResourceManager.GetString("OldPasswordRequired", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Password is required!. + /// internal static string PasswordRequired { get { return ResourceManager.GetString("PasswordRequired", resourceCulture); } } - internal static string SuccessfulUpdateUserMessage { + /// + /// Looks up a localized string similar to User Created Successfuly!. + /// + internal static string SucceddfulCreateUser { get { - return ResourceManager.GetString("SuccessfulUpdateUserMessage", resourceCulture); + return ResourceManager.GetString("SucceddfulCreateUser", resourceCulture); } } - internal static string LoginFailedMessage { + + /// + /// Looks up a localized string similar to Category Created successfylly!. + /// + internal static string SuccessfulCreateCategory { get { - return ResourceManager.GetString("LoginFailedMessage", resourceCulture); + return ResourceManager.GetString("SuccessfulCreateCategory", resourceCulture); } } + /// + /// Looks up a localized string similar to User Deleted successfully!. + /// + internal static string SuccessfulDeleteUserMessage { + get { + return ResourceManager.GetString("SuccessfulDeleteUserMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Login was successful!. + /// internal static string SuccessfulLoginMessage { get { return ResourceManager.GetString("SuccessfulLoginMessage", resourceCulture); } } + /// + /// Looks up a localized string similar to Logout was successful!. + /// + internal static string SuccessfulLogoutMessage { + get { + return ResourceManager.GetString("SuccessfulLogoutMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User roles updated successfuly!. + /// + internal static string SuccessfulUpdateRolesMessage { + get { + return ResourceManager.GetString("SuccessfulUpdateRolesMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to User updated successfully!. + /// + internal static string SuccessfulUpdateUserMessage { + get { + return ResourceManager.GetString("SuccessfulUpdateUserMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Chosen username already exists. + /// + internal static string UsernameExistsMessage { + get { + return ResourceManager.GetString("UsernameExistsMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Username is required!. + /// + internal static string UsernameRequired { + get { + return ResourceManager.GetString("UsernameRequired", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Could not find user!. + /// + internal static string UserNotFoundMessage { + get { + return ResourceManager.GetString("UserNotFoundMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Entered old password is wrong. + /// + internal static string WrongOldPasswordMessage { + get { + return ResourceManager.GetString("WrongOldPasswordMessage", resourceCulture); + } + } } } diff --git a/RelationshipAnalysis.Test/Resources.resx b/RelationshipAnalysis.Test/Resources.resx index 265d43a..371fade 100644 --- a/RelationshipAnalysis.Test/Resources.resx +++ b/RelationshipAnalysis.Test/Resources.resx @@ -1,11 +1,6 @@ - + - - - Chosen username already exists - - Chosen email already exists @@ -13,7 +8,7 @@ Logout was successful! - Password must be at least 8 characters long and contain one uppercase letter, one lowercase letter, one number, and one special character. + Password must contain one digit from 1 to 9, one lowercase letter, one uppercase letter, one special character, no space, and it must be 8-16 characters long. Could not find user! @@ -36,9 +31,12 @@ User updated successfully! + + User Deleted successfully! + - + @@ -53,4 +51,37 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Chosen username already exists + + + User Created Successfuly! + + + Roles cant be empty! + + + Roles are invalid! + + + User roles updated successfuly! + + + Login Failed! + + + Login was successful! + + + You cant delete your account! + + + Input Dto can not be null! + + + Category Name is not unique! + + + Category Created successfylly! + \ No newline at end of file diff --git a/RelationshipAnalysis.Test/Services/CategoryServices/EdgeCategory/CreateEdgeCategoryServiceTests.cs b/RelationshipAnalysis.Test/Services/CategoryServices/EdgeCategory/CreateEdgeCategoryServiceTests.cs new file mode 100644 index 0000000..74d012b --- /dev/null +++ b/RelationshipAnalysis.Test/Services/CategoryServices/EdgeCategory/CreateEdgeCategoryServiceTests.cs @@ -0,0 +1,94 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto.Category; +using RelationshipAnalysis.Enums; +using RelationshipAnalysis.Services.CategoryServices.EdgeCategory; + +namespace RelationshipAnalysis.Test.Services.CategoryServices.EdgeCategory; + +public class CreateEdgeCategoryServiceTests +{ + private readonly CreateEdgeCategoryService _sut; + private readonly IServiceProvider _serviceProvider; + + public CreateEdgeCategoryServiceTests() + { + var serviceCollection = new ServiceCollection(); + + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) + .Options; + + serviceCollection.AddScoped(_ => new ApplicationDbContext(options)); + + _serviceProvider = serviceCollection.BuildServiceProvider(); + + _sut = new(_serviceProvider); + + SeedDatabase(); + } + + private void SeedDatabase() + { + using var scope = _serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + context.EdgeCategories.Add(new Models.Graph.EdgeCategory() + { + EdgeCategoryName = "ExistName" + }); + context.SaveChanges(); + } + + [Fact] + public async Task CreateEdgeCategory_ShouldReturnBadRequest_WhenDtoIsNull() + { + // Arrange + CreateEdgeCategoryDto dto = null; + + // Act + var result = await _sut.CreateEdgeCategory(dto); + + // Assert + Assert.Equal(StatusCodeType.BadRequest, result.StatusCode); + Assert.Equal(Resources.NullDtoErrorMessage, result.Data.Message); + } + + [Fact] + public async Task CreateEdgeCategory_ShouldReturnBadRequest_WhenCategoryNameIsNotUnique() + { + // Arrange + var dto = new CreateEdgeCategoryDto() + { + EdgeCategoryName = "ExistName" + }; + + // Act + var result = await _sut.CreateEdgeCategory(dto); + + // Assert + Assert.Equal(StatusCodeType.BadRequest, result.StatusCode); + Assert.Equal(Resources.NotUniqueCategoryNameErrorMessage, result.Data.Message); + } + + [Fact] + public async Task CreateEdgeCategory_ShouldReturnSuccess_WhenDtoIsOk() + { + // Arrange + var dto = new CreateEdgeCategoryDto() + { + EdgeCategoryName = "NotExistName" + }; + using var scope = _serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + + // Act + var result = await _sut.CreateEdgeCategory(dto); + var categoty = context.EdgeCategories.SingleOrDefault(c => c.EdgeCategoryName == dto.EdgeCategoryName); + + // Assert + Assert.Equal(StatusCodeType.Success, result.StatusCode); + Assert.Equal(Resources.SuccessfulCreateCategory, result.Data.Message); + Assert.NotNull(categoty); + } +} \ No newline at end of file diff --git a/RelationshipAnalysis.Test/Services/CategoryServices/EdgeCategory/EdgeCategoryReceiverTests.cs b/RelationshipAnalysis.Test/Services/CategoryServices/EdgeCategory/EdgeCategoryReceiverTests.cs new file mode 100644 index 0000000..d045dd1 --- /dev/null +++ b/RelationshipAnalysis.Test/Services/CategoryServices/EdgeCategory/EdgeCategoryReceiverTests.cs @@ -0,0 +1,74 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Services.CategoryServices.EdgeCategory; + +namespace RelationshipAnalysis.Test.Services.CategoryServices.EdgeCategory; + +public class EdgeCategoryReceiverTests +{ + private readonly EdgeCategoryReceiver _sut; + private readonly IServiceProvider _serviceProvider; + + private Models.Graph.EdgeCategory Edge1 = new () + { + EdgeCategoryName = "Edge1" + }; + private Models.Graph.EdgeCategory Edge2 = new () + { + EdgeCategoryName = "Edge2" + }; + + public EdgeCategoryReceiverTests() + { + var serviceCollection = new ServiceCollection(); + + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) + .Options; + + serviceCollection.AddScoped(_ => new ApplicationDbContext(options)); + + _serviceProvider = serviceCollection.BuildServiceProvider(); + + _sut = new(_serviceProvider); + + } + + private void SeedDatabase() + { + using var scope = _serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + context.EdgeCategories.AddRange(new List() + { + Edge1, Edge2 + }); + context.SaveChanges(); + } + + [Fact] + public async Task GetAllEdgeCategories_ShouldReturnEmptyList_WhenThereIsNoCategory() + { + // Arrange + + // Act + var result = await _sut.GetAllEdgeCategories(); + + // Assert + Assert.Empty(result); + } + + [Fact] + public async Task GetAllEdgeCategories_ShouldReturnCorrectList_WhenThereIsSomeCategories() + { + // Arrange + SeedDatabase(); + + // Act + var result = await _sut.GetAllEdgeCategories(); + + // Assert + Assert.Contains(Edge1.EdgeCategoryName, result); + Assert.Contains(Edge2.EdgeCategoryName, result); + } +} \ No newline at end of file diff --git a/RelationshipAnalysis.Test/Services/CategoryServices/NodeCategory/CreateNodeCategoryServiceTests.cs b/RelationshipAnalysis.Test/Services/CategoryServices/NodeCategory/CreateNodeCategoryServiceTests.cs new file mode 100644 index 0000000..b0e5764 --- /dev/null +++ b/RelationshipAnalysis.Test/Services/CategoryServices/NodeCategory/CreateNodeCategoryServiceTests.cs @@ -0,0 +1,94 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto.Category; +using RelationshipAnalysis.Enums; +using RelationshipAnalysis.Services.CategoryServices.NodeCategory; + +namespace RelationshipAnalysis.Test.Services.CategoryServices.NodeCategory; + +public class CreateNodeCategoryServiceTests +{ + private readonly CreateNodeCategoryService _sut; + private readonly IServiceProvider _serviceProvider; + + public CreateNodeCategoryServiceTests() + { + var serviceCollection = new ServiceCollection(); + + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) + .Options; + + serviceCollection.AddScoped(_ => new ApplicationDbContext(options)); + + _serviceProvider = serviceCollection.BuildServiceProvider(); + + _sut = new(_serviceProvider); + + SeedDatabase(); + } + + private void SeedDatabase() + { + using var scope = _serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + context.NodeCategories.Add(new Models.Graph.NodeCategory() + { + NodeCategoryName = "ExistName" + }); + context.SaveChanges(); + } + + [Fact] + public async Task CreateNodeCategory_ShouldReturnBadRequest_WhenDtoIsNull() + { + // Arrange + CreateNodeCategoryDto dto = null; + + // Act + var result = await _sut.CreateNodeCategory(dto); + + // Assert + Assert.Equal(StatusCodeType.BadRequest, result.StatusCode); + Assert.Equal(Resources.NullDtoErrorMessage, result.Data.Message); + } + + [Fact] + public async Task CreateNodeCategory_ShouldReturnBadRequest_WhenCategoryNameIsNotUnique() + { + // Arrange + var dto = new CreateNodeCategoryDto() + { + NodeCategoryName = "ExistName" + }; + + // Act + var result = await _sut.CreateNodeCategory(dto); + + // Assert + Assert.Equal(StatusCodeType.BadRequest, result.StatusCode); + Assert.Equal(Resources.NotUniqueCategoryNameErrorMessage, result.Data.Message); + } + + [Fact] + public async Task CreateNodeCategory_ShouldReturnSuccess_WhenDtoIsOk() + { + // Arrange + var dto = new CreateNodeCategoryDto() + { + NodeCategoryName = "NotExistName" + }; + using var scope = _serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + + // Act + var result = await _sut.CreateNodeCategory(dto); + var categoty = context.NodeCategories.SingleOrDefault(c => c.NodeCategoryName == dto.NodeCategoryName); + + // Assert + Assert.Equal(StatusCodeType.Success, result.StatusCode); + Assert.Equal(Resources.SuccessfulCreateCategory, result.Data.Message); + Assert.NotNull(categoty); + } +} \ No newline at end of file diff --git a/RelationshipAnalysis.Test/Services/CategoryServices/NodeCategory/NodeCategoryReceiverTests.cs b/RelationshipAnalysis.Test/Services/CategoryServices/NodeCategory/NodeCategoryReceiverTests.cs new file mode 100644 index 0000000..a0f8e62 --- /dev/null +++ b/RelationshipAnalysis.Test/Services/CategoryServices/NodeCategory/NodeCategoryReceiverTests.cs @@ -0,0 +1,74 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Services.CategoryServices.NodeCategory; + +namespace RelationshipAnalysis.Test.Services.CategoryServices.NodeCategory; + +public class NodeCategoryReceiverTests +{ + private readonly NodeCategoryReceiver _sut; + private readonly IServiceProvider _serviceProvider; + + private Models.Graph.NodeCategory Node1 = new () + { + NodeCategoryName = "Node1" + }; + private Models.Graph.NodeCategory Node2 = new () + { + NodeCategoryName = "Node2" + }; + + public NodeCategoryReceiverTests() + { + var serviceCollection = new ServiceCollection(); + + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) + .Options; + + serviceCollection.AddScoped(_ => new ApplicationDbContext(options)); + + _serviceProvider = serviceCollection.BuildServiceProvider(); + + _sut = new NodeCategoryReceiver(_serviceProvider); + + } + + private void SeedDatabase() + { + using var scope = _serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + context.NodeCategories.AddRange(new List() + { + Node1, Node2 + }); + context.SaveChanges(); + } + + [Fact] + public async Task GetAllNodeCategories_ShouldReturnEmptyList_WhenThereIsNoCategory() + { + // Arrange + + // Act + var result = await _sut.GetAllNodeCategories(); + + // Assert + Assert.Empty(result); + } + + [Fact] + public async Task GetAllNodeCategories_ShouldReturnCorrectList_WhenThereIsSomeCategories() + { + // Arrange + SeedDatabase(); + + // Act + var result = await _sut.GetAllNodeCategories(); + + // Assert + Assert.Contains(Node1.NodeCategoryName, result); + Assert.Contains(Node2.NodeCategoryName, result); + } +} \ No newline at end of file diff --git a/RelationshipAnalysis.Test/Services/GraphReceiverTests.cs b/RelationshipAnalysis.Test/Services/GraphReceiverTests.cs new file mode 100644 index 0000000..848984c --- /dev/null +++ b/RelationshipAnalysis.Test/Services/GraphReceiverTests.cs @@ -0,0 +1,106 @@ +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto.Graph; +using RelationshipAnalysis.Models.Graph; +using RelationshipAnalysis.Services.GraphServices; + +namespace RelationshipAnalysis.Test.Services; + +public class GraphReceiverTests +{ + private readonly GraphReceiver _sut; + private readonly ApplicationDbContext _context; + private readonly IServiceProvider _serviceProvider; + + public GraphReceiverTests() + { + + _context = new ApplicationDbContext(new DbContextOptionsBuilder() + .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()).Options); + + var serviceCollection = new ServiceCollection(); + serviceCollection.AddScoped(_ => _context); + + _serviceProvider = serviceCollection.BuildServiceProvider(); + + _sut = new GraphReceiver(_serviceProvider); + } + + [Fact] + public async Task GetGraph_ShouldReturnGraph_WhenDatabaseHasData() + { + // Arrange + var nodeCategory1 = new NodeCategory { NodeCategoryName = "Account" }; + var nodeCategory2 = new NodeCategory { NodeCategoryName = "Person" }; + + var node1 = new Node + { + NodeUniqueString = "Node1", + NodeCategory = nodeCategory1, + NodeCategoryId = nodeCategory1.NodeCategoryId + }; + + var node2 = new Node + { + NodeUniqueString = "Node2", + NodeCategory = nodeCategory2, + NodeCategoryId = nodeCategory2.NodeCategoryId + }; + + var edgeCategory = new EdgeCategory { EdgeCategoryName = "Transaction"}; + + + _context.NodeCategories.Add(nodeCategory1); + _context.NodeCategories.Add(nodeCategory2); + _context.Nodes.Add(node1); + _context.Nodes.Add(node2); + _context.EdgeCategories.Add(edgeCategory); + + + var edge = new Edge + { + EdgeSourceNodeId = node1.NodeId, + EdgeDestinationNodeId = node2.NodeId, + EdgeCategory = edgeCategory, + EdgeCategoryId = edgeCategory.EdgeCategoryId, + EdgeUniqueString = "Edge1" + }; + + _context.Edges.Add(edge); + + await _context.SaveChangesAsync(); + + + var expectedNodes = new List() + { + new NodeDto() + { + id = node1.NodeId.ToString(), + label = $"{node1.NodeCategory.NodeCategoryName}/{node1.NodeUniqueString}" + }, + new NodeDto() + { + id = node2.NodeId.ToString(), + label = $"{node2.NodeCategory.NodeCategoryName}/{node2.NodeUniqueString}" + } + }; + + var expectedEdges = new List() + { + new EdgeDto() + { + id = edge.EdgeId.ToString(), + source = node1.NodeId.ToString(), + target = node2.NodeId.ToString() + } + }; + // Act + var resultGraph = await _sut.GetGraph(); + + // Assert + Assert.Equivalent(expectedNodes, resultGraph.nodes); + Assert.Equivalent(expectedEdges, resultGraph.edges); + } + +} \ No newline at end of file diff --git a/RelationshipAnalysis.Test/Services/UserInfoServiceTests.cs b/RelationshipAnalysis.Test/Services/UserInfoServiceTests.cs index 88e78d1..5f52ec3 100644 --- a/RelationshipAnalysis.Test/Services/UserInfoServiceTests.cs +++ b/RelationshipAnalysis.Test/Services/UserInfoServiceTests.cs @@ -24,13 +24,13 @@ public UserInfoServiceTests() } [Fact] - public void GetUserAsync_ReturnsNotFound_WhenUserIsNull() + public async Task GetUserAsync_ReturnsNotFound_WhenUserIsNull() { // Arrange User user = null; // Act - var result = _service.GetUser(user); + var result = await _service.GetUser(user); // Assert Assert.Equal(StatusCodeType.NotFound, result.StatusCode); @@ -38,7 +38,7 @@ public void GetUserAsync_ReturnsNotFound_WhenUserIsNull() } [Fact] - public void GetUserAsync_ReturnsSuccess_WhenUserIsNotNull_() + public async Task GetUserAsync_ReturnsSuccess_WhenUserIsNotNull_() { // Arrange var user = new User { Username = "Admin" }; @@ -50,7 +50,7 @@ public void GetUserAsync_ReturnsSuccess_WhenUserIsNotNull_() _rolesReceiver.ReceiveRoles(user.Id).Returns(roles); // Act - var result = _service.GetUser(user); + var result = await _service.GetUser(user); // Assert Assert.Equal(StatusCodeType.Success, result.StatusCode); diff --git a/RelationshipAnalysis.Test/Services/UserRolesReceiverTests.cs b/RelationshipAnalysis.Test/Services/UserRolesReceiverTests.cs index 13474bb..d647126 100644 --- a/RelationshipAnalysis.Test/Services/UserRolesReceiverTests.cs +++ b/RelationshipAnalysis.Test/Services/UserRolesReceiverTests.cs @@ -55,13 +55,13 @@ private void SeedDatabase() } [Fact] - public void ReceiveRoles_ReturnsRoles_WhenUserIdIsValid() + public async Task ReceiveRoles_ReturnsRoles_WhenUserIdIsValid() { // Arrange var userId = 1; // Act - var result = _sut.ReceiveRoles(userId); + var result = await _sut.ReceiveRoles(userId); // Assert Assert.NotNull(result); @@ -71,13 +71,13 @@ public void ReceiveRoles_ReturnsRoles_WhenUserIdIsValid() } [Fact] - public void ReceiveRoles_ReturnsEmptyList_WhenUserIdHasNoRoles() + public async Task ReceiveRoles_ReturnsEmptyList_WhenUserIdHasNoRoles() { // Arrange var userId = 3; // Non-existent user ID // Act - var result = _sut.ReceiveRoles(userId); + var result = await _sut.ReceiveRoles(userId); // Assert Assert.NotNull(result); @@ -85,13 +85,13 @@ public void ReceiveRoles_ReturnsEmptyList_WhenUserIdHasNoRoles() } [Fact] - public void ReceiveRoles_ReturnsEmptyList_WhenUserIdIsInvalid() + public async Task ReceiveRoles_ReturnsEmptyList_WhenUserIdIsInvalid() { // Arrange var userId = 99; // Invalid user ID // Act - var result = _sut.ReceiveRoles(userId); + var result = await _sut.ReceiveRoles(userId); // Assert Assert.NotNull(result); diff --git a/RelationshipAnalysis/Controllers/AdminController.cs b/RelationshipAnalysis/Controllers/AdminController.cs index 1ad22bb..89d71b9 100644 --- a/RelationshipAnalysis/Controllers/AdminController.cs +++ b/RelationshipAnalysis/Controllers/AdminController.cs @@ -27,15 +27,15 @@ public class AdminController( public async Task GetUser(int id) { var user = await userReceiver.ReceiveUserAsync(id); - var result = userInfoService.GetUser(user); + var result = await userInfoService.GetUser(user); return StatusCode((int)result.StatusCode, result.Data); } [HttpGet] - public IActionResult GetAllUser([FromQuery] int page, [FromQuery] int size) + public async Task GetAllUser([FromQuery] int page, [FromQuery] int size) { var users = userReceiver.ReceiveAllUser(page, size); - var result = allUserService.GetAllUser(users); + var result = await allUserService.GetAllUser(users); return StatusCode((int)result.StatusCode, result.Data); } diff --git a/RelationshipAnalysis/Controllers/CategoryController.cs b/RelationshipAnalysis/Controllers/CategoryController.cs new file mode 100644 index 0000000..6f4e67b --- /dev/null +++ b/RelationshipAnalysis/Controllers/CategoryController.cs @@ -0,0 +1,47 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http.HttpResults; +using Microsoft.AspNetCore.Mvc; +using RelationshipAnalysis.Dto.Category; +using RelationshipAnalysis.Services.CategoryServices.EdgeCategory.Abstraction; +using RelationshipAnalysis.Services.CategoryServices.NodeCategory.Abstraction; + +namespace RelationshipAnalysis.Controllers; + +[Authorize] +[ApiController] +[Route("api/[controller]/[action]")] +public class CategoryController( + ICreateEdgeCategoryService createEdgeCategoryService, + ICreateNodeCategoryService createNodeCategoryService, + IEdgeCategoryReceiver edgeCategoryReceiver, + INodeCategoryReceiver nodeCategoryReceiver +) : ControllerBase +{ + [HttpGet] + public async Task GetAllNodeCategories() + { + var result = await nodeCategoryReceiver.GetAllNodeCategories(); + return Ok(result); + } + + [HttpGet] + public async Task GetAllEdgeCategories() + { + var result = await edgeCategoryReceiver.GetAllEdgeCategories(); + return Ok(result); + } + + [HttpPost] + public async Task CreateNodeCategory([FromBody] CreateNodeCategoryDto createNodeCategoryDto) + { + var result = await createNodeCategoryService.CreateNodeCategory(createNodeCategoryDto); + return StatusCode((int)result.StatusCode, result.Data); + } + + [HttpPost] + public async Task CreateEdgeCategory([FromBody] CreateEdgeCategoryDto createEdgeCategoryDto) + { + var result = await createEdgeCategoryService.CreateEdgeCategory(createEdgeCategoryDto); + return StatusCode((int)result.StatusCode, result.Data); + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Controllers/GraphController.cs b/RelationshipAnalysis/Controllers/GraphController.cs new file mode 100644 index 0000000..33260a4 --- /dev/null +++ b/RelationshipAnalysis/Controllers/GraphController.cs @@ -0,0 +1,18 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using RelationshipAnalysis.Services.GraphServices.Abstraction; + +namespace RelationshipAnalysis.Controllers; + + +[ApiController] +[Authorize] +[Route("api/[controller]/[action]")] +public class GraphController(IGraphReceiver graphReceiver) : ControllerBase +{ + [HttpGet] + public async Task GetGraph() + { + return Ok(await graphReceiver.GetGraph()); + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Controllers/UserController.cs b/RelationshipAnalysis/Controllers/UserController.cs index 0985627..f425a55 100644 --- a/RelationshipAnalysis/Controllers/UserController.cs +++ b/RelationshipAnalysis/Controllers/UserController.cs @@ -21,7 +21,7 @@ public class UserController( public async Task GetUser() { var user = await userReceiver.ReceiveUserAsync(User); - var result = userInfoService.GetUser(user); + var result = await userInfoService.GetUser(user); return StatusCode((int)result.StatusCode, result.Data); } diff --git a/RelationshipAnalysis/Dto/Category/CreateEdgeCategoryDto.cs b/RelationshipAnalysis/Dto/Category/CreateEdgeCategoryDto.cs new file mode 100644 index 0000000..a5a335f --- /dev/null +++ b/RelationshipAnalysis/Dto/Category/CreateEdgeCategoryDto.cs @@ -0,0 +1,8 @@ +using System.ComponentModel.DataAnnotations; + +namespace RelationshipAnalysis.Dto.Category; + +public class CreateEdgeCategoryDto +{ + [Required] public string EdgeCategoryName { get; init; } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Dto/Category/CreateNodeCategoryDto.cs b/RelationshipAnalysis/Dto/Category/CreateNodeCategoryDto.cs new file mode 100644 index 0000000..46e7ec6 --- /dev/null +++ b/RelationshipAnalysis/Dto/Category/CreateNodeCategoryDto.cs @@ -0,0 +1,8 @@ +using System.ComponentModel.DataAnnotations; + +namespace RelationshipAnalysis.Dto.Category; + +public class CreateNodeCategoryDto +{ + [Required] public string NodeCategoryName { get; init; } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Dto/Graph/EdgeDto.cs b/RelationshipAnalysis/Dto/Graph/EdgeDto.cs new file mode 100644 index 0000000..9df680b --- /dev/null +++ b/RelationshipAnalysis/Dto/Graph/EdgeDto.cs @@ -0,0 +1,8 @@ +namespace RelationshipAnalysis.Dto.Graph; + +public class EdgeDto +{ + public string id { get; set; } + public string source { get; set; } + public string target { get; set; } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Dto/Graph/GraphDto.cs b/RelationshipAnalysis/Dto/Graph/GraphDto.cs new file mode 100644 index 0000000..c4f8a85 --- /dev/null +++ b/RelationshipAnalysis/Dto/Graph/GraphDto.cs @@ -0,0 +1,7 @@ +namespace RelationshipAnalysis.Dto.Graph; + +public class GraphDto +{ + public List nodes { get; set; } = new List(); + public List edges { get; set; } = new List(); +} \ No newline at end of file diff --git a/RelationshipAnalysis/Dto/Graph/NodeDto.cs b/RelationshipAnalysis/Dto/Graph/NodeDto.cs new file mode 100644 index 0000000..0cea721 --- /dev/null +++ b/RelationshipAnalysis/Dto/Graph/NodeDto.cs @@ -0,0 +1,10 @@ +namespace RelationshipAnalysis.Dto.Graph; + +public class NodeDto +{ + public string id { + get; + set; + } + public string label { get; set; } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Program.cs b/RelationshipAnalysis/Program.cs index c9dba1c..51a0572 100644 --- a/RelationshipAnalysis/Program.cs +++ b/RelationshipAnalysis/Program.cs @@ -1,15 +1,19 @@ -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.IdentityModel.Tokens; using System.Text; -using DotNetEnv; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; using RelationshipAnalysis.Context; using RelationshipAnalysis.Middlewares; -using RelationshipAnalysis.Services; using RelationshipAnalysis.Services.AccessServices; using RelationshipAnalysis.Services.AccessServices.Abstraction; using RelationshipAnalysis.Services.AdminPanelServices; using RelationshipAnalysis.Services.AdminPanelServices.Abstraction; +using RelationshipAnalysis.Services.CategoryServices.EdgeCategory; +using RelationshipAnalysis.Services.CategoryServices.EdgeCategory.Abstraction; +using RelationshipAnalysis.Services.CategoryServices.NodeCategory; +using RelationshipAnalysis.Services.CategoryServices.NodeCategory.Abstraction; +using RelationshipAnalysis.Services.GraphServices; +using RelationshipAnalysis.Services.GraphServices.Abstraction; using RelationshipAnalysis.Services.UserPanelServices; using RelationshipAnalysis.Services.UserPanelServices.Abstraction; using RelationshipAnalysis.Services.UserPanelServices.Abstraction.AuthServices; @@ -39,7 +43,12 @@ .AddSingleton() .AddSingleton() .AddSingleton() - .AddSingleton(); + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton(); builder.Services.Configure(builder.Configuration.GetSection("Jwt")); @@ -93,6 +102,9 @@ app.UseMiddleware(); app.Run(); -public partial class Program +namespace RelationshipAnalysis { + public partial class Program + { + } } \ No newline at end of file diff --git a/RelationshipAnalysis/Resources.Designer.cs b/RelationshipAnalysis/Resources.Designer.cs index 441795f..fd78df8 100644 --- a/RelationshipAnalysis/Resources.Designer.cs +++ b/RelationshipAnalysis/Resources.Designer.cs @@ -158,5 +158,23 @@ internal static string DeleteAccountAccessErrorMessage { } } + internal static string NullDtoErrorMessage { + get { + return ResourceManager.GetString("NullDtoErrorMessage", resourceCulture); + } + } + + internal static string NotUniqueCategoryNameErrorMessage { + get { + return ResourceManager.GetString("NotUniqueCategoryNameErrorMessage", resourceCulture); + } + } + + internal static string SuccessfulCreateCategory { + get { + return ResourceManager.GetString("SuccessfulCreateCategory", resourceCulture); + } + } + } } diff --git a/RelationshipAnalysis/Resources.resx b/RelationshipAnalysis/Resources.resx index 875b072..741c22c 100644 --- a/RelationshipAnalysis/Resources.resx +++ b/RelationshipAnalysis/Resources.resx @@ -75,4 +75,13 @@ You cant delete your account! + + Input Dto can not be null! + + + Category Name is not unique! + + + Category Created successfylly! + \ No newline at end of file diff --git a/RelationshipAnalysis/Services/AdminPanelServices/Abstraction/IAllUserService.cs b/RelationshipAnalysis/Services/AdminPanelServices/Abstraction/IAllUserService.cs index 6744c9c..d802007 100644 --- a/RelationshipAnalysis/Services/AdminPanelServices/Abstraction/IAllUserService.cs +++ b/RelationshipAnalysis/Services/AdminPanelServices/Abstraction/IAllUserService.cs @@ -5,6 +5,6 @@ namespace RelationshipAnalysis.Services.AdminPanelServices.Abstraction; public interface IAllUserService { - ActionResponse GetAllUser(List users); - int ReceiveAllUserCount(); + Task> GetAllUser(List users); + Task ReceiveAllUserCount(); } \ No newline at end of file diff --git a/RelationshipAnalysis/Services/AdminPanelServices/Abstraction/IRoleReceiver.cs b/RelationshipAnalysis/Services/AdminPanelServices/Abstraction/IRoleReceiver.cs index 4a499a7..b2e9deb 100644 --- a/RelationshipAnalysis/Services/AdminPanelServices/Abstraction/IRoleReceiver.cs +++ b/RelationshipAnalysis/Services/AdminPanelServices/Abstraction/IRoleReceiver.cs @@ -2,7 +2,7 @@ namespace RelationshipAnalysis.Services.AdminPanelServices.Abstraction; public interface IRoleReceiver { - List ReceiveRoles(int userId); + Task> ReceiveRoles(int userId); - List ReceiveAllRoles(); + Task> ReceiveAllRoles(); } \ No newline at end of file diff --git a/RelationshipAnalysis/Services/AdminPanelServices/AllUserService.cs b/RelationshipAnalysis/Services/AdminPanelServices/AllUserService.cs index acdf0f9..d8d1efd 100644 --- a/RelationshipAnalysis/Services/AdminPanelServices/AllUserService.cs +++ b/RelationshipAnalysis/Services/AdminPanelServices/AllUserService.cs @@ -1,4 +1,5 @@ using AutoMapper; +using Microsoft.EntityFrameworkCore; using Microsoft.IdentityModel.Tokens; using RelationshipAnalysis.Context; using RelationshipAnalysis.Dto; @@ -10,43 +11,43 @@ namespace RelationshipAnalysis.Services.AdminPanelServices; public class AllUserService(IServiceProvider serviceProvider, IMapper mapper, IRoleReceiver rolesReceiver) : IAllUserService { - public int ReceiveAllUserCount() + public async Task ReceiveAllUserCount() { using var scope = serviceProvider.CreateScope(); var context = scope.ServiceProvider.GetRequiredService(); - var users = context.Users.ToList(); + var users = await context.Users.ToListAsync(); return users.Count; } - public ActionResponse GetAllUser(List users) + public async Task> GetAllUser(List users) { if (users.IsNullOrEmpty()) { return NotFoundResult(); } - var usersList = GetAllUsersList(users); - var result = GetAllUsersOutPut(usersList); + var usersList = await GetAllUsersList(users); + var result = await GetAllUsersOutPut(usersList); return SuccessResult(result); } - private GetAllUsersDto GetAllUsersOutPut(List usersList) + private async Task GetAllUsersOutPut(List usersList) { return new GetAllUsersDto() { Users = usersList, - AllUserCount = ReceiveAllUserCount() + AllUserCount = await ReceiveAllUserCount() }; } - private List GetAllUsersList(List users) + private async Task> GetAllUsersList(List users) { var userOutputs = new List(); foreach (var user in users) { var data = new UserOutputInfoDto(); mapper.Map(user, data); - data.Roles = rolesReceiver.ReceiveRoles(user.Id); + data.Roles = await rolesReceiver.ReceiveRoles(user.Id); userOutputs.Add(data); } diff --git a/RelationshipAnalysis/Services/AdminPanelServices/RoleReceiver.cs b/RelationshipAnalysis/Services/AdminPanelServices/RoleReceiver.cs index f133396..212c744 100644 --- a/RelationshipAnalysis/Services/AdminPanelServices/RoleReceiver.cs +++ b/RelationshipAnalysis/Services/AdminPanelServices/RoleReceiver.cs @@ -1,3 +1,4 @@ +using Microsoft.EntityFrameworkCore; using RelationshipAnalysis.Context; using RelationshipAnalysis.Services.AdminPanelServices.Abstraction; @@ -5,19 +6,19 @@ namespace RelationshipAnalysis.Services.AdminPanelServices; public class RoleReceiver(IServiceProvider serviceProvider) : IRoleReceiver { - public List ReceiveRoles(int userId) + public async Task> ReceiveRoles(int userId) { using var scope = serviceProvider.CreateScope(); var context = scope.ServiceProvider.GetRequiredService(); - return context.UserRoles.ToList().FindAll(ur => ur.UserId == userId) + return (await context.UserRoles.ToListAsync()).FindAll(ur => ur.UserId == userId) .Select(ur => ur.Role.Name).ToList(); } - public List ReceiveAllRoles() + public async Task> ReceiveAllRoles() { using var scope = serviceProvider.CreateScope(); var context = scope.ServiceProvider.GetRequiredService(); - return context.Roles.Select(x => x.Name).ToList(); + return await context.Roles.Select(x => x.Name).ToListAsync(); } } \ No newline at end of file diff --git a/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/Abstraction/ICreateEdgeCategoryService.cs b/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/Abstraction/ICreateEdgeCategoryService.cs new file mode 100644 index 0000000..5fa3aaf --- /dev/null +++ b/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/Abstraction/ICreateEdgeCategoryService.cs @@ -0,0 +1,9 @@ +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Dto.Category; + +namespace RelationshipAnalysis.Services.CategoryServices.EdgeCategory.Abstraction; + +public interface ICreateEdgeCategoryService +{ + Task> CreateEdgeCategory(CreateEdgeCategoryDto createEdgeCategoryDto); +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/Abstraction/IEdgeCategoryReceiver.cs b/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/Abstraction/IEdgeCategoryReceiver.cs new file mode 100644 index 0000000..b0b9ab6 --- /dev/null +++ b/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/Abstraction/IEdgeCategoryReceiver.cs @@ -0,0 +1,6 @@ +namespace RelationshipAnalysis.Services.CategoryServices.EdgeCategory.Abstraction; + +public interface IEdgeCategoryReceiver +{ + Task> GetAllEdgeCategories(); +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/CreateEdgeCategoryService.cs b/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/CreateEdgeCategoryService.cs new file mode 100644 index 0000000..70c00ed --- /dev/null +++ b/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/CreateEdgeCategoryService.cs @@ -0,0 +1,61 @@ +using Microsoft.AspNetCore.Mvc; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Dto.Category; +using RelationshipAnalysis.Enums; +using RelationshipAnalysis.Services.CategoryServices.EdgeCategory.Abstraction; + +namespace RelationshipAnalysis.Services.CategoryServices.EdgeCategory; + +public class CreateEdgeCategoryService(IServiceProvider serviceProvider) : ICreateEdgeCategoryService +{ + public async Task> CreateEdgeCategory(CreateEdgeCategoryDto createEdgeCategoryDto) + { + if (createEdgeCategoryDto is null) + { + return BadRequestResult(Resources.NullDtoErrorMessage); + } + if (IsNotUniqueCategoryName(createEdgeCategoryDto)) + { + return BadRequestResult(Resources.NotUniqueCategoryNameErrorMessage); + } + await AddCategory(createEdgeCategoryDto); + return SuccessfulResult(Resources.SuccessfulCreateCategory); + } + + private ActionResponse SuccessfulResult(string message) + { + return new ActionResponse() + { + Data = new MessageDto(message), + StatusCode = StatusCodeType.Success + }; + } + + private async Task AddCategory(CreateEdgeCategoryDto createEdgeCategoryDto) + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + await context.EdgeCategories.AddAsync(new Models.Graph.EdgeCategory() + { + EdgeCategoryName = createEdgeCategoryDto.EdgeCategoryName + }); + await context.SaveChangesAsync(); + } + + private bool IsNotUniqueCategoryName(CreateEdgeCategoryDto dto) + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + return context.EdgeCategories.Any(c => c.EdgeCategoryName == dto.EdgeCategoryName); + } + + private ActionResponse BadRequestResult(string message) + { + return new ActionResponse() + { + Data = new MessageDto(message), + StatusCode = StatusCodeType.BadRequest + }; + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/EdgeCategoryReceiver.cs b/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/EdgeCategoryReceiver.cs new file mode 100644 index 0000000..c6bfac0 --- /dev/null +++ b/RelationshipAnalysis/Services/CategoryServices/EdgeCategory/EdgeCategoryReceiver.cs @@ -0,0 +1,17 @@ +using Microsoft.EntityFrameworkCore; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Dto.Category; +using RelationshipAnalysis.Services.CategoryServices.EdgeCategory.Abstraction; + +namespace RelationshipAnalysis.Services.CategoryServices.EdgeCategory; + +public class EdgeCategoryReceiver(IServiceProvider serviceProvider) : IEdgeCategoryReceiver +{ + public async Task> GetAllEdgeCategories() + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + return await context.EdgeCategories.Select(e => e.EdgeCategoryName).ToListAsync(); + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/CategoryServices/NodeCategory/Abstraction/ICreateNodeCategoryService.cs b/RelationshipAnalysis/Services/CategoryServices/NodeCategory/Abstraction/ICreateNodeCategoryService.cs new file mode 100644 index 0000000..f28673c --- /dev/null +++ b/RelationshipAnalysis/Services/CategoryServices/NodeCategory/Abstraction/ICreateNodeCategoryService.cs @@ -0,0 +1,9 @@ +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Dto.Category; + +namespace RelationshipAnalysis.Services.CategoryServices.NodeCategory.Abstraction; + +public interface ICreateNodeCategoryService +{ + Task> CreateNodeCategory(CreateNodeCategoryDto createNodeCategoryDto); +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/CategoryServices/NodeCategory/Abstraction/INodeCategoryReceiver.cs b/RelationshipAnalysis/Services/CategoryServices/NodeCategory/Abstraction/INodeCategoryReceiver.cs new file mode 100644 index 0000000..7514441 --- /dev/null +++ b/RelationshipAnalysis/Services/CategoryServices/NodeCategory/Abstraction/INodeCategoryReceiver.cs @@ -0,0 +1,6 @@ +namespace RelationshipAnalysis.Services.CategoryServices.NodeCategory.Abstraction; + +public interface INodeCategoryReceiver +{ + Task> GetAllNodeCategories(); +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/CategoryServices/NodeCategory/CreateNodeCategoryService.cs b/RelationshipAnalysis/Services/CategoryServices/NodeCategory/CreateNodeCategoryService.cs new file mode 100644 index 0000000..66ba8be --- /dev/null +++ b/RelationshipAnalysis/Services/CategoryServices/NodeCategory/CreateNodeCategoryService.cs @@ -0,0 +1,59 @@ +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Dto.Category; +using RelationshipAnalysis.Enums; +using RelationshipAnalysis.Services.CategoryServices.NodeCategory.Abstraction; + +namespace RelationshipAnalysis.Services.CategoryServices.NodeCategory; + +public class CreateNodeCategoryService(IServiceProvider serviceProvider) : ICreateNodeCategoryService +{ + public async Task> CreateNodeCategory(CreateNodeCategoryDto createNodeCategoryDto) + { + if (createNodeCategoryDto is null) + { + return BadRequestResult(Resources.NullDtoErrorMessage); + } + if (IsNotUniqueCategoryName(createNodeCategoryDto)) + { + return BadRequestResult(Resources.NotUniqueCategoryNameErrorMessage); + } + await AddCategory(createNodeCategoryDto); + return SuccessfulResult(Resources.SuccessfulCreateCategory); + } + private ActionResponse SuccessfulResult(string message) + { + return new ActionResponse() + { + Data = new MessageDto(message), + StatusCode = StatusCodeType.Success + }; + } + + private async Task AddCategory(CreateNodeCategoryDto createNodeCategoryDto) + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + await context.NodeCategories.AddAsync(new Models.Graph.NodeCategory() + { + NodeCategoryName = createNodeCategoryDto.NodeCategoryName + }); + await context.SaveChangesAsync(); + } + + private bool IsNotUniqueCategoryName(CreateNodeCategoryDto dto) + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + return context.NodeCategories.Any(c => c.NodeCategoryName == dto.NodeCategoryName); + } + + private ActionResponse BadRequestResult(string message) + { + return new ActionResponse() + { + Data = new MessageDto(message), + StatusCode = StatusCodeType.BadRequest + }; + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/CategoryServices/NodeCategory/NodeCategoryReceiver.cs b/RelationshipAnalysis/Services/CategoryServices/NodeCategory/NodeCategoryReceiver.cs new file mode 100644 index 0000000..2111036 --- /dev/null +++ b/RelationshipAnalysis/Services/CategoryServices/NodeCategory/NodeCategoryReceiver.cs @@ -0,0 +1,15 @@ +using Microsoft.EntityFrameworkCore; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Services.CategoryServices.NodeCategory.Abstraction; + +namespace RelationshipAnalysis.Services.CategoryServices.NodeCategory; + +public class NodeCategoryReceiver(IServiceProvider serviceProvider) : INodeCategoryReceiver +{ + public async Task> GetAllNodeCategories() + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + return await context.NodeCategories.Select(e => e.NodeCategoryName).ToListAsync(); + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/GraphServices/Abstraction/IGraphReceiver.cs b/RelationshipAnalysis/Services/GraphServices/Abstraction/IGraphReceiver.cs new file mode 100644 index 0000000..a9f71c7 --- /dev/null +++ b/RelationshipAnalysis/Services/GraphServices/Abstraction/IGraphReceiver.cs @@ -0,0 +1,9 @@ + +using RelationshipAnalysis.Dto.Graph; + +namespace RelationshipAnalysis.Services.GraphServices.Abstraction; + +public interface IGraphReceiver +{ + Task GetGraph(); +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/GraphServices/GraphReceiver.cs b/RelationshipAnalysis/Services/GraphServices/GraphReceiver.cs new file mode 100644 index 0000000..bcdb3ac --- /dev/null +++ b/RelationshipAnalysis/Services/GraphServices/GraphReceiver.cs @@ -0,0 +1,34 @@ +using AngleSharp.Dom; +using Microsoft.EntityFrameworkCore; +using RelationshipAnalysis.Context; +using RelationshipAnalysis.Dto; +using RelationshipAnalysis.Dto.Graph; +using RelationshipAnalysis.Services.GraphServices.Abstraction; + +namespace RelationshipAnalysis.Services.GraphServices; + +public class GraphReceiver(IServiceProvider serviceProvider): IGraphReceiver +{ + public async Task GetGraph() + { + using var scope = serviceProvider.CreateScope(); + var context = scope.ServiceProvider.GetRequiredService(); + + var contextNodes = await context.Nodes.ToListAsync(); + var contextEdges = await context.Edges.ToListAsync(); + + var resultGraphDto = new GraphDto(); + contextNodes.ForEach(n => resultGraphDto.nodes.Add(new NodeDto() + { + id = n.NodeId.ToString(), + label = $"{n.NodeCategory.NodeCategoryName}/{n.NodeUniqueString}" + })); + contextEdges.ForEach(e => resultGraphDto.edges.Add(new EdgeDto() + { + id = e.EdgeId.ToString(), + source = e.EdgeSourceNodeId.ToString(), + target = e.EdgeDestinationNodeId.ToString() + })); + return resultGraphDto; + } +} \ No newline at end of file diff --git a/RelationshipAnalysis/Services/UserPanelServices/Abstraction/IUserInfoService.cs b/RelationshipAnalysis/Services/UserPanelServices/Abstraction/IUserInfoService.cs index a5175ef..31615bf 100644 --- a/RelationshipAnalysis/Services/UserPanelServices/Abstraction/IUserInfoService.cs +++ b/RelationshipAnalysis/Services/UserPanelServices/Abstraction/IUserInfoService.cs @@ -5,5 +5,5 @@ namespace RelationshipAnalysis.Services.UserPanelServices.Abstraction; public interface IUserInfoService { - ActionResponse GetUser(User user); + Task> GetUser(User user); } \ No newline at end of file diff --git a/RelationshipAnalysis/Services/UserPanelServices/UserInfoService.cs b/RelationshipAnalysis/Services/UserPanelServices/UserInfoService.cs index 6114a87..5460f70 100644 --- a/RelationshipAnalysis/Services/UserPanelServices/UserInfoService.cs +++ b/RelationshipAnalysis/Services/UserPanelServices/UserInfoService.cs @@ -9,20 +9,20 @@ namespace RelationshipAnalysis.Services.UserPanelServices; public class UserInfoService(IRoleReceiver rolesReceiver, IMapper mapper) : IUserInfoService { - public ActionResponse GetUser(User user) + public async Task> GetUser(User user) { if (user is null) { return NotFoundResult(); } - return SuccessResult(user); + return await SuccessResult(user); } - private ActionResponse SuccessResult(User user) + private async Task> SuccessResult(User user) { var result = new UserOutputInfoDto(); mapper.Map(user, result); - result.Roles = rolesReceiver.ReceiveRoles(user.Id); + result.Roles = await rolesReceiver.ReceiveRoles(user.Id); return new ActionResponse() {