aboutsummaryrefslogtreecommitdiff
path: root/ExamTemplate/Services/ExamTemplate.Services
diff options
context:
space:
mode:
Diffstat (limited to 'ExamTemplate/Services/ExamTemplate.Services')
-rw-r--r--ExamTemplate/Services/ExamTemplate.Services/Configurations/ServiceUserMappings.cs15
-rw-r--r--ExamTemplate/Services/ExamTemplate.Services/ExamTemplate.Services.csproj20
-rw-r--r--ExamTemplate/Services/ExamTemplate.Services/Interfaces/IBaseService.cs21
-rw-r--r--ExamTemplate/Services/ExamTemplate.Services/Interfaces/ICloudinaryService.cs11
-rw-r--r--ExamTemplate/Services/ExamTemplate.Services/Interfaces/IUserService.cs25
-rw-r--r--ExamTemplate/Services/ExamTemplate.Services/Services/BaseService.cs91
-rw-r--r--ExamTemplate/Services/ExamTemplate.Services/Services/CloudinaryService.cs50
-rw-r--r--ExamTemplate/Services/ExamTemplate.Services/Services/UserService.cs129
8 files changed, 362 insertions, 0 deletions
diff --git a/ExamTemplate/Services/ExamTemplate.Services/Configurations/ServiceUserMappings.cs b/ExamTemplate/Services/ExamTemplate.Services/Configurations/ServiceUserMappings.cs
new file mode 100644
index 0000000..787b90f
--- /dev/null
+++ b/ExamTemplate/Services/ExamTemplate.Services/Configurations/ServiceUserMappings.cs
@@ -0,0 +1,15 @@
+using AutoMapper;
+using ExamTemplate.Data.Models;
+using ExamTemplate.Services.Models.User;
+
+namespace ExamTemplate.Services.Configurations
+{
+ public class ServiceUserMappings : Profile
+ {
+ public ServiceUserMappings()
+ {
+ CreateMap<RegisterUserServiceModel, User>();
+ CreateMap<User, UserServiceModel>();
+ }
+ }
+}
diff --git a/ExamTemplate/Services/ExamTemplate.Services/ExamTemplate.Services.csproj b/ExamTemplate/Services/ExamTemplate.Services/ExamTemplate.Services.csproj
new file mode 100644
index 0000000..b84928f
--- /dev/null
+++ b/ExamTemplate/Services/ExamTemplate.Services/ExamTemplate.Services.csproj
@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <ItemGroup>
+ <ProjectReference Include="..\ExamTemplate.Services.Models\ExamTemplate.Services.Models.csproj" />
+ <ProjectReference Include="..\..\Data\ExamTemplate.Data\ExamTemplate.Data.csproj" />
+ <ProjectReference Include="..\..\Data\ExamTemplate.Data.Models\ExamTemplate.Data.Models.csproj" />
+ <ProjectReference Include="..\..\Common\ExamTemplate.Common\ExamTemplate.Common.csproj" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <PackageReference Include="Automapper" Version="10.1.1" />
+ <PackageReference Include="CloudinaryDotNet" Version="1.15.1" />
+ <PackageReference Include="Microsoft.AspNetCore.Identity" Version="2.2.0" />
+ </ItemGroup>
+
+ <PropertyGroup>
+ <TargetFramework>net5.0</TargetFramework>
+ </PropertyGroup>
+
+</Project>
diff --git a/ExamTemplate/Services/ExamTemplate.Services/Interfaces/IBaseService.cs b/ExamTemplate/Services/ExamTemplate.Services/Interfaces/IBaseService.cs
new file mode 100644
index 0000000..66de7b8
--- /dev/null
+++ b/ExamTemplate/Services/ExamTemplate.Services/Interfaces/IBaseService.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace ExamTemplate.Services.Interfaces
+{
+ public interface IBaseService<DbModel, ServiceModel>
+ where DbModel : class
+ where ServiceModel : class
+ {
+ Task<bool> CreateAsync(ServiceModel serviceModel);
+
+ Task<ServiceModel> GetByIdAsync(Guid id);
+
+ Task<List<ServiceModel>> GetAllAsync();
+
+ Task<bool> EditAsync(ServiceModel serviceModel);
+
+ Task<bool> DeleteAsync(Guid id);
+ }
+}
diff --git a/ExamTemplate/Services/ExamTemplate.Services/Interfaces/ICloudinaryService.cs b/ExamTemplate/Services/ExamTemplate.Services/Interfaces/ICloudinaryService.cs
new file mode 100644
index 0000000..9c4d884
--- /dev/null
+++ b/ExamTemplate/Services/ExamTemplate.Services/Interfaces/ICloudinaryService.cs
@@ -0,0 +1,11 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Http;
+
+namespace ExamTemplate.Services.Interfaces
+{
+ public interface ICloudinaryService
+ {
+ Task<List<string>> UploadFilesToCloud(List<IFormFile> formFiles);
+ }
+}
diff --git a/ExamTemplate/Services/ExamTemplate.Services/Interfaces/IUserService.cs b/ExamTemplate/Services/ExamTemplate.Services/Interfaces/IUserService.cs
new file mode 100644
index 0000000..35f14e3
--- /dev/null
+++ b/ExamTemplate/Services/ExamTemplate.Services/Interfaces/IUserService.cs
@@ -0,0 +1,25 @@
+using System.Security.Claims;
+using System.Threading.Tasks;
+using ExamTemplate.Services.Models.User;
+
+namespace ExamTemplate.Services.Interfaces
+{
+ public interface IUserService
+ {
+ Task<bool> RegisterUserAsync(RegisterUserServiceModel registerUserServiceModel);
+
+ Task<bool> LoginUserAsync(LoginUserServiceModel loginUserServiceModel);
+
+ Task LogoutAsync();
+
+ Task<UserServiceModel> GetUserByUsernameAsync(string username);
+
+ Task<UserServiceModel> GetUserByClaimsAsync(ClaimsPrincipal claimsPrincipal);
+
+ Task<bool> EditUserAsync(ClaimsPrincipal claimsPrincipal, UserServiceModel userServiceModel);
+
+ Task<bool> DeleteUserAsync(ClaimsPrincipal claimsPrincipal);
+
+ bool IsSignedIn(ClaimsPrincipal claimsPrincipal);
+ }
+}
diff --git a/ExamTemplate/Services/ExamTemplate.Services/Services/BaseService.cs b/ExamTemplate/Services/ExamTemplate.Services/Services/BaseService.cs
new file mode 100644
index 0000000..b1b823e
--- /dev/null
+++ b/ExamTemplate/Services/ExamTemplate.Services/Services/BaseService.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Threading.Tasks;
+using AutoMapper;
+using ExamTemplate.Data;
+using System.Collections.Generic;
+using Microsoft.EntityFrameworkCore;
+using System.Linq;
+using ExamTemplate.Services.Interfaces;
+using ExamTemplate.Common;
+
+namespace ExamTemplate.Services.Services
+{
+ public abstract class BaseService<DbModel, ServiceModel> : IBaseService<DbModel, ServiceModel>
+ where DbModel : class
+ where ServiceModel : class
+ {
+ protected IMapper _autoMapper { get; private set; }
+ protected TemplateContext _context { get; private set; }
+
+ protected BaseService(IMapper autoMapper, TemplateContext context)
+ {
+ this._autoMapper = autoMapper;
+ this._context = context;
+ }
+
+ public virtual async Task<bool> CreateAsync(ServiceModel serviceModel)
+ {
+ if (serviceModel == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(ServiceModel)));
+
+ DbModel newEntity = this._autoMapper.Map<DbModel>(serviceModel);
+
+ await this.GetDbSet()
+ .AddAsync(newEntity);
+
+ return await this.SaveChangesAsync();
+ }
+
+ public virtual async Task<ServiceModel> GetByIdAsync(Guid id)
+ {
+ if (id == Guid.Empty)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(Guid)));
+
+ DbModel entity = await this.GetDbSet()
+ .FindAsync(id);
+
+ return this._autoMapper.Map<ServiceModel>(entity);
+ }
+
+ public virtual async Task<List<ServiceModel>> GetAllAsync()
+ {
+ return await this.GetDbSet()
+ .Select(x => this._autoMapper.Map<ServiceModel>(x))
+ .ToListAsync();
+ }
+
+ public virtual async Task<bool> EditAsync(ServiceModel serviceModel)
+ {
+ if (serviceModel == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(ServiceModel)));
+
+ DbModel entity = this._autoMapper.Map<DbModel>(serviceModel);
+
+ this._context.Update(entity);
+
+ return await this.SaveChangesAsync();
+ }
+
+ public virtual async Task<bool> DeleteAsync(Guid id)
+ {
+ DbModel entity = this.GetDbSet()
+ .Find(id);
+
+ this._context.Remove(entity);
+
+ return await this.SaveChangesAsync();
+ }
+
+ /// Get, Create, Edit and Delete use this method
+ /// Override it to add include statements (and so all other methods will work with includes too)
+ protected virtual DbSet<DbModel> GetDbSet()
+ {
+ return this._context.Set<DbModel>();
+ }
+
+ protected async Task<bool> SaveChangesAsync()
+ {
+ return await this._context.SaveChangesAsync() >= 1;
+ }
+ }
+}
diff --git a/ExamTemplate/Services/ExamTemplate.Services/Services/CloudinaryService.cs b/ExamTemplate/Services/ExamTemplate.Services/Services/CloudinaryService.cs
new file mode 100644
index 0000000..40772d9
--- /dev/null
+++ b/ExamTemplate/Services/ExamTemplate.Services/Services/CloudinaryService.cs
@@ -0,0 +1,50 @@
+using System.Collections.Generic;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using CloudinaryDotNet;
+using CloudinaryDotNet.Actions;
+using Microsoft.AspNetCore.Http;
+using ExamTemplate.Services.Interfaces;
+
+namespace ExamTemplate.Services.Services
+{
+ public class CloudinaryService : ICloudinaryService
+ {
+ // Regex for getting the filename without (final) filename extension
+ // So, from image.png, it will match image, and from doc.my.txt will match doc.my
+ private static readonly Regex s_imageRegex = new(".*(?=\\.)");
+
+ private readonly Cloudinary _cloudinary;
+
+ public CloudinaryService(string cloudName, string apiKey, string apiSecret)
+ {
+ this._cloudinary = new Cloudinary(new Account(cloudName, apiKey, apiSecret));
+ }
+
+ public async Task<List<string>> UploadFilesToCloud(List<IFormFile> formFiles)
+ {
+ List<string> fileUrls = new();
+ foreach (var formFile in formFiles)
+ {
+ string fileName = s_imageRegex.Match(formFile.FileName).ToString();
+
+ using var ms = new MemoryStream();
+ formFile.CopyTo(ms);
+ byte[] formBytes = ms.ToArray();
+
+ RawUploadParams rawUploadParams = new()
+ {
+ File = new FileDescription(fileName, new MemoryStream(formBytes)),
+ PublicId = fileName,
+ UseFilename = true
+ };
+
+ RawUploadResult rawUploadResult = await this._cloudinary.UploadAsync(rawUploadParams);
+ fileUrls.Add(rawUploadResult.Url.AbsoluteUri);
+ }
+
+ return fileUrls;
+ }
+ }
+}
diff --git a/ExamTemplate/Services/ExamTemplate.Services/Services/UserService.cs b/ExamTemplate/Services/ExamTemplate.Services/Services/UserService.cs
new file mode 100644
index 0000000..4e85688
--- /dev/null
+++ b/ExamTemplate/Services/ExamTemplate.Services/Services/UserService.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Security.Claims;
+using System.Threading.Tasks;
+using AutoMapper;
+using ExamTemplate.Data;
+using ExamTemplate.Data.Models;
+using ExamTemplate.Services.Models.User;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.EntityFrameworkCore;
+using ExamTemplate.Services.Interfaces;
+using ExamTemplate.Common;
+
+namespace ExamTemplate.Services.Services
+{
+ public class UserService : IUserService
+ {
+ private readonly IMapper _autoMapper;
+ private readonly TemplateContext _context;
+ private readonly SignInManager<User> _signInManager;
+ private readonly UserManager<User> _userManager;
+ private readonly RoleManager<IdentityRole<Guid>> _roleManager;
+
+ public UserService(IMapper autoMapper, TemplateContext templateContext, SignInManager<User> signInManager, UserManager<User> userManager, RoleManager<IdentityRole<Guid>> roleManager)
+ {
+ this._autoMapper = autoMapper;
+ this._context = templateContext;
+ this._signInManager = signInManager;
+ this._userManager = userManager;
+ this._roleManager = roleManager;
+ }
+
+ public async Task<bool> RegisterUserAsync(RegisterUserServiceModel registerUserServiceModel)
+ {
+ if (registerUserServiceModel == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(RegisterUserServiceModel)));
+
+ User user = this._autoMapper.Map<User>(registerUserServiceModel);
+
+ user.PasswordHash = this._userManager.PasswordHasher.HashPassword(user, registerUserServiceModel.Password);
+ IdentityResult userCreateResult = await this._userManager.CreateAsync(user);
+
+ if (!userCreateResult.Succeeded)
+ {
+ await this._userManager.DeleteAsync(user);
+ return false;
+ }
+
+ IdentityResult addRoleResult;
+ if (await this._userManager.Users.CountAsync() == 1) // 1, because we added the user in line 37
+ addRoleResult = await this._userManager.AddToRoleAsync(user, RoleConst.Admin);
+ else
+ addRoleResult = await this._userManager.AddToRoleAsync(user, RoleConst.User);
+
+ return addRoleResult.Succeeded;
+ }
+
+ public async Task<bool> LoginUserAsync(LoginUserServiceModel loginUserServiceModel)
+ {
+ if (loginUserServiceModel == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(LoginUserServiceModel)));
+
+ SignInResult result = await this._signInManager.PasswordSignInAsync(loginUserServiceModel.Username, loginUserServiceModel.Password, false, false);
+
+ return result.Succeeded;
+ }
+
+ public async Task LogoutAsync()
+ {
+ await this._signInManager.SignOutAsync();
+ }
+
+ public async Task<UserServiceModel> GetUserByUsernameAsync(string username)
+ {
+ if (username == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(string)));
+
+ User user = await this._userManager.Users
+ .FirstOrDefaultAsync(x => x.UserName == username);
+
+ return this._autoMapper.Map<UserServiceModel>(user);
+ }
+
+ public async Task<UserServiceModel> GetUserByClaimsAsync(ClaimsPrincipal claimsPrincipal)
+ {
+ if (claimsPrincipal == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(ClaimsPrincipal)));
+
+ User user = await this._userManager.GetUserAsync(claimsPrincipal);
+
+ return this._autoMapper.Map<UserServiceModel>(user);
+ }
+
+ public async Task<bool> EditUserAsync(ClaimsPrincipal claimsPrincipal, UserServiceModel userServiceModel)
+ {
+ if (claimsPrincipal == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(ClaimsPrincipal)));
+ if (userServiceModel == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(UserServiceModel)));
+
+ User user = await this._userManager.GetUserAsync(claimsPrincipal);
+
+ user.UserName = userServiceModel.Username;
+ user.FirstName = userServiceModel.FirstName;
+ user.LastName = userServiceModel.LastName;
+
+ IdentityResult result = await this._userManager.UpdateAsync(user);
+ return result.Succeeded;
+ }
+
+ public async Task<bool> DeleteUserAsync(ClaimsPrincipal claimsPrincipal)
+ {
+ if (claimsPrincipal == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(ClaimsPrincipal)));
+
+ User user = await this._userManager.GetUserAsync(claimsPrincipal);
+
+ IdentityResult result = await this._userManager.DeleteAsync(user);
+ return result.Succeeded;
+ }
+
+ public bool IsSignedIn(ClaimsPrincipal claimsPrincipal)
+ {
+ if (claimsPrincipal == null)
+ throw new ArgumentNullException(ErrorMessages.NullObject(typeof(ClaimsPrincipal)));
+
+ return this._signInManager.IsSignedIn(claimsPrincipal);
+ }
+ }
+}