Add project files
This commit is contained in:
68
T120B165-ImgBoard/Services/CommentService.cs
Normal file
68
T120B165-ImgBoard/Services/CommentService.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using T120B165_ImgBoard.Data;
|
||||
using T120B165_ImgBoard.Models;
|
||||
using T120B165_ImgBoard.Utils;
|
||||
|
||||
namespace T120B165_ImgBoard.Services;
|
||||
|
||||
public interface ICommentService
|
||||
{
|
||||
Task<Comment> Create(string text, User author, Post post);
|
||||
Task<Comment?> GetById(int commentId);
|
||||
Task<PagedList<Comment>> GetAll(int pageNumber = 1);
|
||||
Task<bool> Delete(Comment comment);
|
||||
Task<Comment> Update(Comment comment);
|
||||
}
|
||||
|
||||
public class CommentService(ImgBoardContext context): ICommentService
|
||||
{
|
||||
private const int PageSize = 20;
|
||||
|
||||
public async Task<Comment> Create(string text, User author, Post post)
|
||||
{
|
||||
var entry = new Comment
|
||||
{
|
||||
Text = text,
|
||||
Author = author,
|
||||
OriginalPost = post,
|
||||
Created = DateTime.Now,
|
||||
};
|
||||
await context.Comments.AddAsync(entry);
|
||||
await context.SaveChangesAsync();
|
||||
return entry;
|
||||
}
|
||||
|
||||
public async Task<Comment?> GetById(int commentId)
|
||||
{
|
||||
return await context.Comments.Where(t => t.Id == commentId)
|
||||
.Include(b => b.Author)
|
||||
.Include(b => b.OriginalPost)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<PagedList<Comment>> GetAll(int pageNumber = 1)
|
||||
{
|
||||
var totalCount = await context.Comments.CountAsync();
|
||||
var items = await context.Comments
|
||||
.Skip((pageNumber - 1) * PageSize)
|
||||
.Take(PageSize)
|
||||
.Include(b => b.Author)
|
||||
.Include(b => b.OriginalPost)
|
||||
.ToListAsync();
|
||||
return new PagedList<Comment>(items, pageNumber, PageSize, totalCount);
|
||||
}
|
||||
|
||||
public async Task<bool> Delete(Comment comment)
|
||||
{
|
||||
context.Comments.Remove(comment);
|
||||
await context.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<Comment> Update(Comment comment)
|
||||
{
|
||||
context.Comments.Update(comment);
|
||||
await context.SaveChangesAsync();
|
||||
return comment;
|
||||
}
|
||||
}
|
||||
34
T120B165-ImgBoard/Services/FileService.cs
Normal file
34
T120B165-ImgBoard/Services/FileService.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using T120B165_ImgBoard.Data;
|
||||
using File = T120B165_ImgBoard.Models.File;
|
||||
|
||||
namespace T120B165_ImgBoard.Services;
|
||||
|
||||
public interface IFileService
|
||||
{
|
||||
public Task<File?> GetFileById(long id);
|
||||
Task<File> Update(File file);
|
||||
Task Delete(File file);
|
||||
}
|
||||
|
||||
public class FileService(ImgBoardContext context): IFileService
|
||||
{
|
||||
public async Task<File?> GetFileById(long id)
|
||||
{
|
||||
return await context.Files.Where(f => f.Id == id).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<File> Update(File file)
|
||||
{
|
||||
context.Files.Update(file);
|
||||
await context.SaveChangesAsync();
|
||||
return file;
|
||||
}
|
||||
|
||||
public async Task Delete(File file)
|
||||
{
|
||||
var actualFile = await GetFileById(file.Id);
|
||||
context.Files.Remove(actualFile);
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
100
T120B165-ImgBoard/Services/PostService.cs
Normal file
100
T120B165-ImgBoard/Services/PostService.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using T120B165_ImgBoard.Data;
|
||||
using T120B165_ImgBoard.Models;
|
||||
using T120B165_ImgBoard.Utils;
|
||||
using File = T120B165_ImgBoard.Models.File;
|
||||
|
||||
namespace T120B165_ImgBoard.Services;
|
||||
|
||||
public interface IPostService
|
||||
{
|
||||
Task<CreatedPost> Create(
|
||||
string title, string description, List<Tag> tags, User author,
|
||||
string fileName, string fileContentType, long fileSize);
|
||||
Task<Post?> GetById(int postId, bool includeUnfinished = false);
|
||||
Task<PagedList<Post>> GetAll(int pageNumber = 1);
|
||||
Task<bool> Delete(Post post);
|
||||
Task<Post> Update(Post post);
|
||||
}
|
||||
|
||||
public record CreatedPost(Post Post, File File);
|
||||
|
||||
public class PostService(ImgBoardContext context): IPostService
|
||||
{
|
||||
private const int PageSize = 20;
|
||||
public async Task<CreatedPost> Create(
|
||||
string title,
|
||||
string description,
|
||||
List<Tag> tags,
|
||||
User author,
|
||||
string fileName,
|
||||
string fileContentType,
|
||||
long fileSize
|
||||
)
|
||||
{
|
||||
var file = new File
|
||||
{
|
||||
OriginalFileName = fileName,
|
||||
Size = fileSize,
|
||||
ContentType = fileContentType,
|
||||
FilePath = Path.GetTempFileName(),
|
||||
CreatedDate = DateTime.Now,
|
||||
};
|
||||
await context.Files.AddAsync(file);
|
||||
|
||||
var entry = new Post
|
||||
{
|
||||
Title = title,
|
||||
Description = description,
|
||||
Author = author,
|
||||
Created = DateTime.Now,
|
||||
Tags = tags,
|
||||
File = file
|
||||
};
|
||||
await context.Posts.AddAsync(entry);
|
||||
await context.SaveChangesAsync();
|
||||
return new CreatedPost(entry, file);
|
||||
}
|
||||
|
||||
public async Task<Post?> GetById(int postId, bool includeUnfinished = false)
|
||||
{
|
||||
var query = context.Posts.Where(t => t.Id == postId);
|
||||
if (!includeUnfinished)
|
||||
{
|
||||
query = query.Where(t => t.File.FinishedDate != null);
|
||||
}
|
||||
|
||||
return await query.Include(b => b.Author)
|
||||
.Include(b => b.Tags)
|
||||
.Include(b => b.File)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<PagedList<Post>> GetAll(int pageNumber = 1)
|
||||
{
|
||||
var totalCount = await context.Posts.Where(p => p.File.FinishedDate != null).CountAsync();
|
||||
var items = await context.Posts
|
||||
.Skip((pageNumber - 1) * PageSize)
|
||||
.Take(PageSize)
|
||||
.Where(p => p.File.FinishedDate != null)
|
||||
.Include(b => b.Author)
|
||||
.Include(b => b.Tags)
|
||||
.Include(b => b.File)
|
||||
.ToListAsync();
|
||||
return new PagedList<Post>(items, pageNumber, PageSize, totalCount);
|
||||
}
|
||||
|
||||
public async Task<bool> Delete(Post post)
|
||||
{
|
||||
context.Posts.Remove(post);
|
||||
await context.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<Post> Update(Post post)
|
||||
{
|
||||
context.Posts.Update(post);
|
||||
await context.SaveChangesAsync();
|
||||
return post;
|
||||
}
|
||||
}
|
||||
68
T120B165-ImgBoard/Services/TagService.cs
Normal file
68
T120B165-ImgBoard/Services/TagService.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using T120B165_ImgBoard.Data;
|
||||
using T120B165_ImgBoard.Dtos;
|
||||
using T120B165_ImgBoard.Models;
|
||||
using T120B165_ImgBoard.Utils;
|
||||
|
||||
namespace T120B165_ImgBoard.Services;
|
||||
|
||||
public interface ITagService
|
||||
{
|
||||
Task<Tag?> GetByName(string name);
|
||||
|
||||
Task<bool> DeleteByName(string name);
|
||||
|
||||
Task<PagedList<Tag>> GetAll(int pageNumber = 1);
|
||||
|
||||
Task<Tag> Update(Tag tag, TagType type);
|
||||
|
||||
Task<Tag> Create(TagType type, string name);
|
||||
}
|
||||
|
||||
public class TagService(ImgBoardContext context): ITagService
|
||||
{
|
||||
public async Task<Tag?> GetByName(string name)
|
||||
{
|
||||
return await context.Tags.Where(t => t.Name == name).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<PagedList<Tag>> GetAll(int pageNumber)
|
||||
{
|
||||
int pageSize = 20;
|
||||
var totalCount = await context.Tags.CountAsync();
|
||||
var products = await context.Tags
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
return new PagedList<Tag>(products, pageNumber, pageSize, totalCount);;
|
||||
}
|
||||
|
||||
public async Task<Tag> Update(Tag tag, TagType type)
|
||||
{
|
||||
tag.Type = type;
|
||||
context.Tags.Update(tag);
|
||||
await context.SaveChangesAsync();
|
||||
return tag;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteByName(string name)
|
||||
{
|
||||
var tag = await context.Tags.FindAsync(name);
|
||||
if (tag == null) return false;
|
||||
context.Tags.Remove(tag);
|
||||
await context.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<Tag> Create(TagType type, string name)
|
||||
{
|
||||
var tag = new Tag
|
||||
{
|
||||
Name = name,
|
||||
Type = type,
|
||||
};
|
||||
await context.Tags.AddAsync(tag);
|
||||
await context.SaveChangesAsync();
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
74
T120B165-ImgBoard/Services/TokenService.cs
Normal file
74
T120B165-ImgBoard/Services/TokenService.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using T120B165_ImgBoard.Data;
|
||||
using T120B165_ImgBoard.Models;
|
||||
|
||||
namespace T120B165_ImgBoard.Services;
|
||||
|
||||
public interface ITokenService
|
||||
{
|
||||
Task<string> GenerateJwtToken(User user);
|
||||
Task<string> GenerateRefreshToken(User user);
|
||||
|
||||
Task<RefreshToken?> GetRefreshTokenByValue(string refreshToken);
|
||||
Task<bool> InvalidateRefreshToken(RefreshToken refreshToken);
|
||||
}
|
||||
|
||||
public class TokenService(ImgBoardContext context, IConfiguration config, UserManager<User> userManager): ITokenService
|
||||
{
|
||||
|
||||
public async Task<RefreshToken?> GetRefreshTokenByValue(string refreshToken)
|
||||
{
|
||||
return await context.RefreshTokens.Where(t => t.Token == refreshToken && t.Expires > DateTime.Now)
|
||||
.Include(t => t.User)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> InvalidateRefreshToken(RefreshToken refreshToken)
|
||||
{
|
||||
context.RefreshTokens.Remove(refreshToken);
|
||||
await context.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<string> GenerateJwtToken(User user)
|
||||
{
|
||||
var roles = await userManager.GetRolesAsync(user);
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new(JwtRegisteredClaimNames.Sub, user.Id),
|
||||
new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
|
||||
new(JwtRegisteredClaimNames.Email, user.Email)
|
||||
};
|
||||
claims.AddRange(roles.Select(role => new Claim(ClaimTypes.Role, role)));
|
||||
|
||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Jwt:Key"]));
|
||||
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||
|
||||
var token = new JwtSecurityToken(
|
||||
issuer: config["Jwt:Issuer"],
|
||||
audience: config["Jwt:Audience"],
|
||||
claims: claims,
|
||||
expires: DateTime.Now.AddMinutes(Convert.ToDouble(config["Jwt:DurationInMinutes"])),
|
||||
signingCredentials: creds);
|
||||
|
||||
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||
}
|
||||
|
||||
public async Task<string> GenerateRefreshToken(User user)
|
||||
{
|
||||
var token = new RefreshToken
|
||||
{
|
||||
Expires = DateTime.Now.AddDays(30),
|
||||
Token = Guid.NewGuid().ToString(),
|
||||
User = user
|
||||
};
|
||||
await context.RefreshTokens.AddAsync(token);
|
||||
await context.SaveChangesAsync();
|
||||
return token.Token;
|
||||
}
|
||||
}
|
||||
18
T120B165-ImgBoard/Services/UserService.cs
Normal file
18
T120B165-ImgBoard/Services/UserService.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using T120B165_ImgBoard.Data;
|
||||
using T120B165_ImgBoard.Models;
|
||||
|
||||
namespace T120B165_ImgBoard.Services;
|
||||
|
||||
public interface IUserService
|
||||
{
|
||||
public Task<User?> GetUserById(string id);
|
||||
}
|
||||
|
||||
public class UserService(ImgBoardContext context): IUserService
|
||||
{
|
||||
public async Task<User?> GetUserById(string id)
|
||||
{
|
||||
return await context.Users.Where(u => u.Id == id).FirstOrDefaultAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user