diff options
Diffstat (limited to 'ExamTemplate/Services/ExamTemplate.Services')
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);
+ }
+ }
+}
|
