aboutsummaryrefslogtreecommitdiff
path: root/src/Services
diff options
context:
space:
mode:
authorVictor S <57849063+transtrike@users.noreply.github.com>2021-04-02 23:55:25 +0300
committerGitHub <noreply@github.com>2021-04-02 23:55:25 +0300
commitbad7456b379bcc683431e2279591f7c5227bd55a (patch)
treeb82e15d10e28759dcd066b38ccdd16c23753b33c /src/Services
parent2448c4d31188aed26605c5e3c282bacc3bd71ae5 (diff)
parentb0c6c6e1795a1cc8fe82a60ce16a263ab4cad397 (diff)
downloadDevHive-bad7456b379bcc683431e2279591f7c5227bd55a.tar
DevHive-bad7456b379bcc683431e2279591f7c5227bd55a.tar.gz
DevHive-bad7456b379bcc683431e2279591f7c5227bd55a.zip
Merge pull request #24 from Team-Kaleidoscope/feature/profile_picture_implementation
- Removed InsertProfilePicture from Service layer (unneeded) - ReadProfilePicture endpoint implemented
Diffstat (limited to 'src/Services')
-rw-r--r--src/Services/DevHive.Services.Models/ProfilePicture/ProfilePictureServiceModel.cs11
-rw-r--r--src/Services/DevHive.Services.Models/User/ProfilePictureServiceModel.cs7
-rw-r--r--src/Services/DevHive.Services.Models/User/UpdateProfilePictureServiceModel.cs12
-rw-r--r--src/Services/DevHive.Services.Models/User/UserServiceModel.cs2
-rw-r--r--src/Services/DevHive.Services.Tests/ProfilePictureService.Tests.cs84
-rw-r--r--src/Services/DevHive.Services/Interfaces/IProfilePictureService.cs30
-rw-r--r--src/Services/DevHive.Services/Interfaces/IUserService.cs8
-rw-r--r--src/Services/DevHive.Services/Services/ProfilePictureService.cs101
-rw-r--r--src/Services/DevHive.Services/Services/UserService.cs22
9 files changed, 227 insertions, 50 deletions
diff --git a/src/Services/DevHive.Services.Models/ProfilePicture/ProfilePictureServiceModel.cs b/src/Services/DevHive.Services.Models/ProfilePicture/ProfilePictureServiceModel.cs
new file mode 100644
index 0000000..5e69d13
--- /dev/null
+++ b/src/Services/DevHive.Services.Models/ProfilePicture/ProfilePictureServiceModel.cs
@@ -0,0 +1,11 @@
+using System;
+using Microsoft.AspNetCore.Http;
+
+namespace DevHive.Services.Models.ProfilePicture
+{
+ public class ProfilePictureServiceModel
+ {
+ public Guid UserId { get; set; }
+ public IFormFile ProfilePictureFormFile { get; set; }
+ }
+}
diff --git a/src/Services/DevHive.Services.Models/User/ProfilePictureServiceModel.cs b/src/Services/DevHive.Services.Models/User/ProfilePictureServiceModel.cs
deleted file mode 100644
index cbe64b2..0000000
--- a/src/Services/DevHive.Services.Models/User/ProfilePictureServiceModel.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace DevHive.Services.Models.User
-{
- public class ProfilePictureServiceModel
- {
- public string ProfilePictureURL { get; set; }
- }
-}
diff --git a/src/Services/DevHive.Services.Models/User/UpdateProfilePictureServiceModel.cs b/src/Services/DevHive.Services.Models/User/UpdateProfilePictureServiceModel.cs
deleted file mode 100644
index 19ba08f..0000000
--- a/src/Services/DevHive.Services.Models/User/UpdateProfilePictureServiceModel.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-using System;
-using Microsoft.AspNetCore.Http;
-
-namespace DevHive.Services.Models.User
-{
- public class UpdateProfilePictureServiceModel
- {
- public Guid UserId { get; set; }
-
- public IFormFile Picture { get; set; }
- }
-}
diff --git a/src/Services/DevHive.Services.Models/User/UserServiceModel.cs b/src/Services/DevHive.Services.Models/User/UserServiceModel.cs
index 04b618b..f48c703 100644
--- a/src/Services/DevHive.Services.Models/User/UserServiceModel.cs
+++ b/src/Services/DevHive.Services.Models/User/UserServiceModel.cs
@@ -8,7 +8,7 @@ namespace DevHive.Services.Models.User
{
public class UserServiceModel : BaseUserServiceModel
{
- public string ProfilePictureURL { get; set; }
+ public string ProfilePictureURL { get; set; } = new(string.Empty);
public HashSet<RoleServiceModel> Roles { get; set; } = new();
diff --git a/src/Services/DevHive.Services.Tests/ProfilePictureService.Tests.cs b/src/Services/DevHive.Services.Tests/ProfilePictureService.Tests.cs
new file mode 100644
index 0000000..a7a2963
--- /dev/null
+++ b/src/Services/DevHive.Services.Tests/ProfilePictureService.Tests.cs
@@ -0,0 +1,84 @@
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using DevHive.Data;
+using DevHive.Data.Interfaces;
+using DevHive.Data.Models;
+using DevHive.Data.Repositories;
+using DevHive.Services.Interfaces;
+using DevHive.Services.Models.ProfilePicture;
+using DevHive.Services.Services;
+using Microsoft.AspNetCore.Http;
+using Microsoft.EntityFrameworkCore;
+using Moq;
+using NUnit.Framework;
+
+namespace DevHive.Services.Tests
+{
+ [TestFixture]
+ public class ProfilePictureServiceTests
+ {
+ private DevHiveContext _context;
+ private Mock<IUserRepository> _userRepositoryMock;
+ private Mock<ProfilePictureRepository> _profilePictureRepository;
+ private Mock<ICloudService> _cloudService;
+ private ProfilePictureService _profilePictureService;
+
+ [SetUp]
+ public void Setup()
+ {
+ DbContextOptionsBuilder<DevHiveContext> options = new DbContextOptionsBuilder<DevHiveContext>()
+ .UseInMemoryDatabase("DevHive_UserRepository_Database");
+ this._context = new DevHiveContext(options.Options);
+ this._userRepositoryMock = new Mock<IUserRepository>();
+ this._profilePictureRepository = new Mock<ProfilePictureRepository>(this._context);
+ this._cloudService = new Mock<ICloudService>();
+
+ this._profilePictureService = new ProfilePictureService(
+ this._userRepositoryMock.Object,
+ this._profilePictureRepository.Object,
+ this._cloudService.Object
+ );
+ }
+
+ [Test]
+ public async Task InsertProfilePicture_ShouldInsertProfilePicToDatabaseAndUploadToCloud()
+ {
+ //Arrange
+ Guid userId = Guid.NewGuid();
+ Mock<IFormFile> fileMock = new();
+
+ //File mocking setup
+ var content = "Hello World from a Fake File";
+ var fileName = "test.jpg";
+ var ms = new MemoryStream();
+ var writer = new StreamWriter(ms);
+ writer.Write(content);
+ writer.Flush();
+ ms.Position = 0;
+ fileMock.Setup(p => p.FileName).Returns(fileName);
+ fileMock.Setup(p => p.Length).Returns(ms.Length);
+ fileMock.Setup(p => p.OpenReadStream()).Returns(ms);
+
+ //User Setup
+ this._userRepositoryMock
+ .Setup(p => p.GetByIdAsync(userId))
+ .ReturnsAsync(new User()
+ {
+ Id = userId
+ });
+
+ ProfilePictureServiceModel profilePictureServiceModel = new()
+ {
+ UserId = userId,
+ ProfilePictureFormFile = fileMock.Object
+ };
+
+ //Act
+ string profilePicURL = await this._profilePictureService.InsertProfilePicture(profilePictureServiceModel);
+
+ //Assert
+ Assert.IsNotEmpty(profilePicURL);
+ }
+ }
+}
diff --git a/src/Services/DevHive.Services/Interfaces/IProfilePictureService.cs b/src/Services/DevHive.Services/Interfaces/IProfilePictureService.cs
new file mode 100644
index 0000000..edf2775
--- /dev/null
+++ b/src/Services/DevHive.Services/Interfaces/IProfilePictureService.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Threading.Tasks;
+using DevHive.Services.Models.ProfilePicture;
+
+namespace DevHive.Services.Interfaces
+{
+ public interface IProfilePictureService
+ {
+ /// <summary>
+ /// Get a profile picture by it's Guid
+ /// </summary>
+ /// <param name="id">Profile picture's Guid</param>
+ /// <returns>The profile picture's URL in the cloud</returns>
+ Task<string> GetProfilePictureById(Guid id);
+
+ /// <summary>
+ /// Uploads the given picture and assigns it's link to the user in the database
+ /// </summary>
+ /// <param name="profilePictureServiceModel">Contains User's Guid and the new picture to be updated</param>
+ /// <returns>The new profile picture's URL in the cloud</returns>
+ Task<string> UpdateProfilePicture(ProfilePictureServiceModel profilePictureServiceModel);
+
+ /// <summary>
+ /// Delete a profile picture from the cloud and the database
+ /// </summary>
+ /// <param name="id">The profile picture's Guid</param>
+ /// <returns>True if the picture is deleted, false otherwise</returns>
+ Task<bool> DeleteProfilePicture(Guid id);
+ }
+}
diff --git a/src/Services/DevHive.Services/Interfaces/IUserService.cs b/src/Services/DevHive.Services/Interfaces/IUserService.cs
index a55f9dd..da07507 100644
--- a/src/Services/DevHive.Services/Interfaces/IUserService.cs
+++ b/src/Services/DevHive.Services/Interfaces/IUserService.cs
@@ -45,14 +45,6 @@ namespace DevHive.Services.Interfaces
Task<UserServiceModel> UpdateUser(UpdateUserServiceModel updateUserServiceModel);
/// <summary>
- /// Uploads the given picture and assigns it's link to the user in the database
- /// Requires authenticated user
- /// </summary>
- /// <param name="updateProfilePictureServiceModel">Contains User's Guid and the new picture to be updated</param>
- /// <returns>The new picture's URL</returns>
- Task<ProfilePictureServiceModel> UpdateProfilePicture(UpdateProfilePictureServiceModel updateProfilePictureServiceModel);
-
- /// <summary>
/// Deletes a user from the database and removes his data entirely
/// Requires authenticated user
/// </summary>
diff --git a/src/Services/DevHive.Services/Services/ProfilePictureService.cs b/src/Services/DevHive.Services/Services/ProfilePictureService.cs
new file mode 100644
index 0000000..1de2114
--- /dev/null
+++ b/src/Services/DevHive.Services/Services/ProfilePictureService.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using DevHive.Data.Interfaces;
+using DevHive.Data.Models;
+using DevHive.Services.Interfaces;
+using DevHive.Services.Models.ProfilePicture;
+using Microsoft.AspNetCore.Http;
+
+namespace DevHive.Services.Services
+{
+ public class ProfilePictureService : IProfilePictureService
+ {
+ private readonly IUserRepository _userRepository;
+ private readonly IProfilePictureRepository _profilePictureRepository;
+ private readonly ICloudService _cloudinaryService;
+
+ public ProfilePictureService(IUserRepository userRepository, IProfilePictureRepository profilePictureRepository, ICloudService cloudinaryService)
+ {
+ this._userRepository = userRepository;
+ this._profilePictureRepository = profilePictureRepository;
+ this._cloudinaryService = cloudinaryService;
+ }
+
+ public async Task<string> GetProfilePictureById(Guid id)
+ {
+ return (await this._profilePictureRepository.GetByIdAsync(id)).PictureURL;
+ }
+
+ public async Task<string> UpdateProfilePicture(ProfilePictureServiceModel profilePictureServiceModel)
+ {
+ ValidateProfPic(profilePictureServiceModel.ProfilePictureFormFile);
+ await ValidateUserExistsAsync(profilePictureServiceModel.UserId);
+
+ User user = await this._userRepository.GetByIdAsync(profilePictureServiceModel.UserId);
+ // if (user.ProfilePicture.PictureURL != ProfilePicture.DefaultURL)
+ if (user.ProfilePicture.Id != Guid.Empty)
+ {
+ List<string> file = new() { user.ProfilePicture.PictureURL };
+ bool removed = await this._cloudinaryService.RemoveFilesFromCloud(file);
+
+ if (!removed)
+ throw new ArgumentException("Cannot delete old picture");
+ }
+
+ return await SaveProfilePictureInDatabase(profilePictureServiceModel);
+ }
+
+ public async Task<bool> DeleteProfilePicture(Guid id)
+ {
+ ProfilePicture profilePic = await this._profilePictureRepository.GetByIdAsync(id) ??
+ throw new ArgumentException("Such picture doesn't exist!");
+
+ bool removedFromDb = await this._profilePictureRepository.DeleteAsync(profilePic);
+ if (!removedFromDb)
+ throw new ArgumentException("Cannot delete picture from database!");
+
+ List<string> file = new() { profilePic.PictureURL };
+ bool removedFromCloud = await this._cloudinaryService.RemoveFilesFromCloud(file);
+ if (!removedFromCloud)
+ throw new ArgumentException("Cannot delete picture from cloud!");
+
+ return true;
+ }
+
+ private async Task<string> SaveProfilePictureInDatabase(ProfilePictureServiceModel profilePictureServiceModel)
+ {
+ List<IFormFile> file = new() { profilePictureServiceModel.ProfilePictureFormFile };
+ string picUrl = (await this._cloudinaryService.UploadFilesToCloud(file))[0];
+ ProfilePicture profilePic = new() { PictureURL = picUrl };
+
+ User user = await this._userRepository.GetByIdAsync(profilePictureServiceModel.UserId);
+ profilePic.UserId = user.Id;
+ profilePic.User = user;
+
+ bool success = await this._profilePictureRepository.AddAsync(profilePic);
+ if (!success)
+ throw new ArgumentException("Unable to upload picture!");
+
+ user.ProfilePicture = profilePic;
+ bool userProfilePicAlter = await this._userRepository.EditAsync(user.Id, user);
+
+ if (!userProfilePicAlter)
+ throw new ArgumentException("Unable to alter user's profile picture");
+
+ return picUrl;
+ }
+
+ private static void ValidateProfPic(IFormFile profilePictureFormFile)
+ {
+ if (profilePictureFormFile.Length == 0)
+ throw new ArgumentException("Picture cannot be null");
+ }
+
+ private async Task ValidateUserExistsAsync(Guid userId)
+ {
+ if (!await this._userRepository.DoesUserExistAsync(userId))
+ throw new ArgumentException("User does not exist!");
+ }
+ }
+}
diff --git a/src/Services/DevHive.Services/Services/UserService.cs b/src/Services/DevHive.Services/Services/UserService.cs
index 4f74b06..d487de4 100644
--- a/src/Services/DevHive.Services/Services/UserService.cs
+++ b/src/Services/DevHive.Services/Services/UserService.cs
@@ -119,28 +119,6 @@ namespace DevHive.Services.Services
User newUser = await this._userRepository.GetByIdAsync(user.Id);
return this._userMapper.Map<UserServiceModel>(newUser);
}
-
- public async Task<ProfilePictureServiceModel> UpdateProfilePicture(UpdateProfilePictureServiceModel updateProfilePictureServiceModel)
- {
- User user = await this._userRepository.GetByIdAsync(updateProfilePictureServiceModel.UserId);
-
- if (!string.IsNullOrEmpty(user.ProfilePicture.PictureURL))
- {
- bool success = await _cloudService.RemoveFilesFromCloud(new List<string> { user.ProfilePicture.PictureURL });
- if (!success)
- throw new InvalidCastException("Could not delete old profile picture!");
- }
-
- string fileUrl = (await this._cloudService.UploadFilesToCloud(new List<IFormFile> { updateProfilePictureServiceModel.Picture }))[0] ??
- throw new ArgumentException("Unable to upload profile picture to cloud");
-
- bool successful = await this._userRepository.UpdateProfilePicture(updateProfilePictureServiceModel.UserId, fileUrl);
-
- if (!successful)
- throw new InvalidOperationException("Unable to change profile picture!");
-
- return new ProfilePictureServiceModel() { ProfilePictureURL = fileUrl };
- }
#endregion
#region Delete