Refactoring: Added interfaces, custom exceptions, UserManager unit tests, dependency injection/inversion; Regex match search by date, keywords

This commit is contained in:
Dimitar Byalkov
2023-06-06 17:52:36 +02:00
parent 180b261d37
commit 53c42a35d8
43 changed files with 668 additions and 211 deletions

View File

@@ -1,20 +1,20 @@
using Models;
using Data;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Logic
{
public class AnnouncementManager
{
private AnnouncementRepository announcementRepository;
public AnnouncementManager()
private IAnnouncementRepository announcementRepository;
public AnnouncementManager(IAnnouncementRepository announcementRepository)
{
announcementRepository = new AnnouncementRepository();
this.announcementRepository = announcementRepository;
}
public List<Announcement> GetAllAnnouncements()
{
@@ -24,22 +24,44 @@ namespace Logic
{
return announcementRepository.GetAnnouncementById(id);
}
public List<Announcement> GetAnnouncementsByPage(int? p, int? c)
public List<Announcement> GetAnnouncementsByPage(int p = 0, int c = 10)
{
return announcementRepository.GetAnnouncementsByPage(p, c);
}
public bool CreateAnnouncement(string title, string description, User author, DateTime publishDate, bool isImportant, bool isSticky)
public void CreateAnnouncement(string title, string description, User author, DateTime publishDate, bool isImportant, bool isSticky)
{
return announcementRepository.CreateAnnouncement(title, description, author, publishDate, isImportant, isSticky);
announcementRepository.CreateAnnouncement(title, description, author, publishDate, isImportant, isSticky);
}
public bool UpdateAnnouncement(int id, string title, string description, bool isImportant, bool isSticky)
public void UpdateAnnouncement(int id, string title, string description, bool isImportant, bool isSticky)
{
description += $"{Environment.NewLine}{Environment.NewLine}Updated: {DateTime.Now.ToString("g")}";
return announcementRepository.UpdateAnnouncement(id, title, description, isImportant, isSticky);
announcementRepository.UpdateAnnouncement(id, title, description, isImportant, isSticky);
}
public bool DeleteAnnouncement(int id)
public void DeleteAnnouncement(int id)
{
return announcementRepository.DeleteAnnouncement(id);
announcementRepository.DeleteAnnouncement(id);
}
public List<Announcement> SearchAnnouncements(string query)
{
if (string.IsNullOrEmpty(query))
{
return new List<Announcement>();
}
else
{
var match = Regex.Match(query, "(?<=date:)[0-9]{4}-[0-9]{2}-[0-9]{2}");
DateTime date;
if (DateTime.TryParse(match.Groups[0].Value, out date))
{
query = Regex.Replace(query, "date:[0-9]{4}-[0-9]{2}-[0-9]{2}", "");
if (string.IsNullOrEmpty(query))
{
return announcementRepository.GetAllAnnouncements().Where(x => x.PublishDate.Date == date.Date).ToList();
}
else return announcementRepository.SearchAnnouncement(query).Where(x => x.PublishDate.Date == date.Date).ToList();
}
else return announcementRepository.SearchAnnouncement(query);
}
}
}
}

View File

@@ -1,5 +1,4 @@
using Models;
using Data;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -10,10 +9,10 @@ namespace Logic
{
public class CommentManager
{
private CommentRepository commentRepository;
public CommentManager()
private ICommentRepository commentRepository;
public CommentManager(ICommentRepository commentRepository)
{
commentRepository = new CommentRepository();
this.commentRepository = commentRepository;
}
public void CreateCommentToAnnouncement(User author, string description, string title, DateTime publishDate, int announcementId)

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace Logic.Exceptions
{
public class DatabaseNetworkException : WebException
{
public DatabaseNetworkException(string? message) : base(message)
{
}
public DatabaseNetworkException(string? message, Exception? innerException) : base(message, innerException)
{
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Logic.Exceptions
{
public class DatabaseOperationException : ApplicationException
{
public DatabaseOperationException(string? message) : base(message)
{
}
public DatabaseOperationException(string? message, Exception? innerException) : base(message, innerException)
{
}
}
}

View File

@@ -0,0 +1,21 @@
using Models;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Logic
{
public interface IAnnouncementRepository
{
public List<Announcement> GetAllAnnouncements();
public Announcement GetAnnouncementById(int id);
public List<Announcement> GetAnnouncementsByPage(int p, int c);
public void CreateAnnouncement(string title, string description, User author, DateTime publishDate, bool isImportant, bool isSticky);
public void UpdateAnnouncement(int id, string title, string description, bool isImportant, bool isSticky);
public void DeleteAnnouncement(int id);
public List<Announcement> SearchAnnouncement(string query);
}
}

View File

@@ -0,0 +1,19 @@
using System.ComponentModel.Design;
using System.Data.SqlClient;
using Models;
namespace Logic;
public interface ICommentRepository
{
public List<Comment> GetAllCommentsOnAnnouncement(int announcementId);
public List<Comment> GetAllCommentResponses(int commentId);
public Comment GetCommentById(int id);
public void UpdateComment(int id, string description);
public Comment CreateComment(User author, string description, string title, DateTime publishDate);
public void CreateCommentOnAnnouncement(User author, string description, string title, DateTime publishDate, int announcementId);
public void CreateResponseOnComment(User author, string description, string title, DateTime publishDate, int commentId);
public void DeleteComment(int id);
public void DeleteCommentOnAnnouncement(int commentId, int announcementId);
public void DeleteResponseOnComment(int responseId, int commentId);
}

View File

@@ -0,0 +1,20 @@
using Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Logic
{
public interface IUserRepository
{
public List<User> GetAllUsers();
public User GetUserById(int id);
public User GetUserByName(string userName);
public List<User> GetUsersByPage(int p, int c);
public User CreateUser(string name, string password, UserRole role);
public void UpdateUser(int id, string name, string password, UserRole role);
public void DisableUser(int id);
}
}

View File

@@ -11,7 +11,6 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Data\Data.csproj" />
<ProjectReference Include="..\Models\Models.csproj" />
</ItemGroup>

View File

@@ -1,6 +1,5 @@
using BCrypt.Net;
using Models;
using Data;
using System;
using System.Collections.Generic;
using System.Data;
@@ -15,10 +14,10 @@ namespace Logic
{
public class UserManager
{
private UserRepository userRepository;
public UserManager()
private readonly IUserRepository userRepository;
public UserManager(IUserRepository userRepository)
{
userRepository = new UserRepository();
this.userRepository = userRepository;
}
public List<User> GetAllUsers()
{
@@ -28,29 +27,38 @@ namespace Logic
{
return userRepository.GetUserById(id);
}
public List<User> GetUsersByPage(int? p, int? c)
public List<User> GetUsersByPage(int p = 0, int c = 10)
{
return userRepository.GetUsersByPage(p, c);
}
public User? AuthenticatedUser(string name, string password)
{
List<User> users = userRepository.GetAllUsers();
User user = users.Find(x => x.Name == name);
if (user == null)
User? user = users.Find(x => x.Name == name);
if (name == null || password == null)
{
return null;
throw new ArgumentNullException();
}
else
if (user != null && BCrypt.Net.BCrypt.Verify(password, user.Password))
{
if (BCrypt.Net.BCrypt.Verify(password, user.Password))
{
return user;
}
else return null;
return user;
}
return null;
}
public bool CreateUser(string name, string password, UserRole role)
public bool UserExists(string name)
{
return userRepository.GetUserByName(name) != null;
}
public User CreateUser(string name, string password, UserRole role)
{
if (UserExists(name))
{
throw new ArgumentException("User with given username already exists!");
}
if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(password))
{
throw new ArgumentException("Name or password should not be empty");
}
return userRepository.CreateUser(name, password, role);
}
public void UpdateUser(int id, string name, string password, UserRole role)