mirror of
https://github.com/Ikatono/ComiServ.git
synced 2025-10-28 20:45:35 -05:00
updated controllers and some services to use async/await
This commit is contained in:
@@ -4,14 +4,13 @@ using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
//using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
[Index(nameof(Name), IsUnique = true)]
|
||||
public class Author
|
||||
{
|
||||
[Index(nameof(Name), IsUnique = true)]
|
||||
public class Author
|
||||
{
|
||||
public int Id { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; } = null!;
|
||||
public ICollection<ComicAuthor> ComicAuthors { get; set; } = null!;
|
||||
}
|
||||
public int Id { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; } = null!;
|
||||
public ICollection<ComicAuthor> ComicAuthors { get; set; } = null!;
|
||||
}
|
||||
|
||||
@@ -3,33 +3,32 @@ using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
[Index(nameof(Handle), IsUnique = true)]
|
||||
[Index(nameof(Filepath), IsUnique = true)]
|
||||
public class Comic
|
||||
{
|
||||
[Index(nameof(Handle), IsUnique = true)]
|
||||
[Index(nameof(Filepath), IsUnique = true)]
|
||||
public class Comic
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public bool Exists { get; set; }
|
||||
//id exposed through the API
|
||||
[Required]
|
||||
[StringLength(ComicsContext.HANDLE_LENGTH)]
|
||||
public string Handle { get; set; } = null!;
|
||||
[Required]
|
||||
public string Filepath { get; set; } = null!;
|
||||
[Required]
|
||||
public string Title { get; set; } = null!;
|
||||
[Required]
|
||||
public string Description { get; set; } = null!;
|
||||
public int PageCount { get; set; }
|
||||
public long SizeBytes { get; set; }
|
||||
public long FileXxhash64 { get; set; }
|
||||
public byte[]? ThumbnailWebp { get; set; }
|
||||
[InverseProperty("Comic")]
|
||||
public ICollection<ComicTag> ComicTags { get; set; } = [];
|
||||
[InverseProperty("Comic")]
|
||||
public ICollection<ComicAuthor> ComicAuthors { get; set; } = [];
|
||||
[InverseProperty("Comic")]
|
||||
public ICollection<ComicRead> ReadBy { get; set; } = [];
|
||||
}
|
||||
public int Id { get; set; }
|
||||
public bool Exists { get; set; }
|
||||
//id exposed through the API
|
||||
[Required]
|
||||
[StringLength(ComicsContext.HANDLE_LENGTH)]
|
||||
public string Handle { get; set; } = null!;
|
||||
[Required]
|
||||
public string Filepath { get; set; } = null!;
|
||||
[Required]
|
||||
public string Title { get; set; } = null!;
|
||||
[Required]
|
||||
public string Description { get; set; } = null!;
|
||||
public int PageCount { get; set; }
|
||||
public long SizeBytes { get; set; }
|
||||
public long FileXxhash64 { get; set; }
|
||||
public byte[]? ThumbnailWebp { get; set; }
|
||||
[InverseProperty("Comic")]
|
||||
public ICollection<ComicTag> ComicTags { get; set; } = [];
|
||||
[InverseProperty("Comic")]
|
||||
public ICollection<ComicAuthor> ComicAuthors { get; set; } = [];
|
||||
[InverseProperty("Comic")]
|
||||
public ICollection<ComicRead> ReadBy { get; set; } = [];
|
||||
}
|
||||
|
||||
@@ -2,20 +2,19 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
[PrimaryKey("ComicId", "AuthorId")]
|
||||
[Index("ComicId")]
|
||||
[Index("AuthorId")]
|
||||
public class ComicAuthor
|
||||
{
|
||||
[PrimaryKey("ComicId", "AuthorId")]
|
||||
[Index("ComicId")]
|
||||
[Index("AuthorId")]
|
||||
public class ComicAuthor
|
||||
{
|
||||
[ForeignKey(nameof(Comic))]
|
||||
public int ComicId { get; set; }
|
||||
[Required]
|
||||
public Comic Comic { get; set; } = null!;
|
||||
[ForeignKey(nameof(Author))]
|
||||
public int AuthorId { get; set; }
|
||||
[Required]
|
||||
public Author Author { get; set; } = null!;
|
||||
}
|
||||
[ForeignKey(nameof(Comic))]
|
||||
public int ComicId { get; set; }
|
||||
[Required]
|
||||
public Comic Comic { get; set; } = null!;
|
||||
[ForeignKey(nameof(Author))]
|
||||
public int AuthorId { get; set; }
|
||||
[Required]
|
||||
public Author Author { get; set; } = null!;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
[PrimaryKey(nameof(UserId), nameof(ComicId))]
|
||||
[Index(nameof(UserId))]
|
||||
[Index(nameof(ComicId))]
|
||||
public class ComicRead
|
||||
{
|
||||
[PrimaryKey(nameof(UserId), nameof(ComicId))]
|
||||
[Index(nameof(UserId))]
|
||||
[Index(nameof(ComicId))]
|
||||
public class ComicRead
|
||||
{
|
||||
public int UserId { get; set; }
|
||||
public User User { get; set; }
|
||||
public int ComicId { get; set; }
|
||||
public Comic Comic { get; set; }
|
||||
}
|
||||
public int UserId { get; set; }
|
||||
public User User { get; set; }
|
||||
public int ComicId { get; set; }
|
||||
public Comic Comic { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
[PrimaryKey("ComicId", "TagId")]
|
||||
[Index("ComicId")]
|
||||
[Index("TagId")]
|
||||
public class ComicTag
|
||||
{
|
||||
[PrimaryKey("ComicId", "TagId")]
|
||||
[Index("ComicId")]
|
||||
[Index("TagId")]
|
||||
public class ComicTag
|
||||
{
|
||||
public int ComicId { get; set; }
|
||||
public Comic Comic { get; set; } = null!;
|
||||
public int TagId { get; set; }
|
||||
public Tag Tag { get; set; } = null!;
|
||||
}
|
||||
public int ComicId { get; set; }
|
||||
public Comic Comic { get; set; } = null!;
|
||||
public int TagId { get; set; }
|
||||
public Tag Tag { get; set; } = null!;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
[PrimaryKey("FileXxhash64")]
|
||||
public class Cover
|
||||
{
|
||||
[PrimaryKey("FileXxhash64")]
|
||||
public class Cover
|
||||
{
|
||||
public long FileXxhash64 { get; set; }
|
||||
public string Filename { get; set; } = null!;
|
||||
public byte[] CoverFile { get; set; } = null!;
|
||||
}
|
||||
public long FileXxhash64 { get; set; }
|
||||
public string Filename { get; set; } = null!;
|
||||
public byte[] CoverFile { get; set; } = null!;
|
||||
}
|
||||
|
||||
@@ -2,36 +2,35 @@
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Swashbuckle.AspNetCore.SwaggerGen;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// This was originally made to remove Entity types that were being added to the Swagger schema.
|
||||
/// I found that there was a bug in `ProducesResponseTypeAttribute` that caused it, and this is
|
||||
/// no longer necessary. I changed Apply to a nop but am keeping this around as an example and
|
||||
/// in case I actually need something like this in the future.
|
||||
/// </summary>
|
||||
public class EntitySwaggerFilter : ISchemaFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// This was originally made to remove Entity types that were being added to the Swagger schema.
|
||||
/// I found that there was a bug in `ProducesResponseTypeAttribute` that caused it, and this is
|
||||
/// no longer necessary. I changed Apply to a nop but am keeping this around as an example and
|
||||
/// in case I actually need something like this in the future.
|
||||
/// </summary>
|
||||
public class EntitySwaggerFilter : ISchemaFilter
|
||||
public readonly static string[] FILTER = [
|
||||
nameof(Author),
|
||||
nameof(Comic),
|
||||
nameof(ComicAuthor),
|
||||
nameof(ComicTag),
|
||||
nameof(Cover),
|
||||
nameof(Tag),
|
||||
nameof(User),
|
||||
nameof(UserType)
|
||||
];
|
||||
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
|
||||
{
|
||||
public readonly static string[] FILTER = [
|
||||
nameof(Author),
|
||||
nameof(Comic),
|
||||
nameof(ComicAuthor),
|
||||
nameof(ComicTag),
|
||||
nameof(Cover),
|
||||
nameof(Tag),
|
||||
nameof(User),
|
||||
nameof(UserType)
|
||||
];
|
||||
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
|
||||
{
|
||||
return;
|
||||
foreach (var item in context.SchemaRepository.Schemas.Keys)
|
||||
{
|
||||
if (FILTER.Contains(item))
|
||||
{
|
||||
context.SchemaRepository.Schemas.Remove(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
//foreach (var item in context.SchemaRepository.Schemas.Keys)
|
||||
//{
|
||||
// if (FILTER.Contains(item))
|
||||
// {
|
||||
// context.SchemaRepository.Schemas.Remove(item);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
[Index(nameof(Name), IsUnique = true)]
|
||||
public class Tag
|
||||
{
|
||||
[Index(nameof(Name), IsUnique = true)]
|
||||
public class Tag
|
||||
{
|
||||
//[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; } = null!;
|
||||
public ICollection<ComicTag> ComicTags { get; set; } = null!;
|
||||
}
|
||||
//[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public int Id { get; set; }
|
||||
[Required]
|
||||
public string Name { get; set; } = null!;
|
||||
public ICollection<ComicTag> ComicTags { get; set; } = null!;
|
||||
}
|
||||
|
||||
@@ -3,36 +3,35 @@ using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
[PrimaryKey(nameof(Id))]
|
||||
[Index(nameof(Username), IsUnique = true)]
|
||||
public class User
|
||||
{
|
||||
[PrimaryKey(nameof(Id))]
|
||||
[Index(nameof(Username), IsUnique = true)]
|
||||
public class User
|
||||
public const int HashLengthBytes = 512 / 8;
|
||||
public const int SaltLengthBytes = HashLengthBytes;
|
||||
public int Id { get; set; }
|
||||
[MaxLength(20)]
|
||||
public string Username { get; set; }
|
||||
[MaxLength(SaltLengthBytes)]
|
||||
public byte[] Salt { get; set; }
|
||||
[MaxLength(HashLengthBytes)]
|
||||
public byte[] HashedPassword { get; set; }
|
||||
public UserType UserType { get; set; }
|
||||
public UserTypeEnum UserTypeId { get; set; }
|
||||
[InverseProperty("User")]
|
||||
public ICollection<ComicRead> ComicsRead { get; set; } = [];
|
||||
//cryptography should probably be in a different class
|
||||
public static byte[] MakeSalt()
|
||||
{
|
||||
public const int HashLengthBytes = 512 / 8;
|
||||
public const int SaltLengthBytes = HashLengthBytes;
|
||||
public int Id { get; set; }
|
||||
[MaxLength(20)]
|
||||
public string Username { get; set; }
|
||||
[MaxLength(SaltLengthBytes)]
|
||||
public byte[] Salt { get; set; }
|
||||
[MaxLength(HashLengthBytes)]
|
||||
public byte[] HashedPassword { get; set; }
|
||||
public UserType UserType { get; set; }
|
||||
public UserTypeEnum UserTypeId { get; set; }
|
||||
[InverseProperty("User")]
|
||||
public ICollection<ComicRead> ComicsRead { get; set; } = [];
|
||||
//cryptography should probably be in a different class
|
||||
public static byte[] MakeSalt()
|
||||
{
|
||||
byte[] arr = new byte[SaltLengthBytes];
|
||||
RandomNumberGenerator.Fill(new Span<byte>(arr));
|
||||
return arr;
|
||||
}
|
||||
public static byte[] Hash(byte[] password, byte[] salt)
|
||||
{
|
||||
var salted = salt.Append((byte)':').Concat(password).ToArray();
|
||||
return SHA512.HashData(salted);
|
||||
}
|
||||
byte[] arr = new byte[SaltLengthBytes];
|
||||
RandomNumberGenerator.Fill(new Span<byte>(arr));
|
||||
return arr;
|
||||
}
|
||||
public static byte[] Hash(byte[] password, byte[] salt)
|
||||
{
|
||||
var salted = salt.Append((byte)':').Concat(password).ToArray();
|
||||
return SHA512.HashData(salted);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,27 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace ComiServ.Entities
|
||||
namespace ComiServ.Entities;
|
||||
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public enum UserTypeEnum
|
||||
{
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public enum UserTypeEnum
|
||||
{
|
||||
//important that this is 0 as a safety precaution,
|
||||
//in case it's accidentally left as default
|
||||
Invalid = 0,
|
||||
//can create accounts
|
||||
Administrator = 1,
|
||||
//has basic access
|
||||
User = 2,
|
||||
//authenticates but does not give access
|
||||
Restricted = 3,
|
||||
//refuses to authenticate but maintains records
|
||||
Disabled = 4,
|
||||
}
|
||||
public class UserType
|
||||
{
|
||||
public UserTypeEnum Id { get; set; }
|
||||
[MaxLength(26)]
|
||||
public string Name { get; set; }
|
||||
public ICollection<User> Users { get; set; }
|
||||
}
|
||||
//important that this is 0 as a safety precaution,
|
||||
//in case it's accidentally left as default
|
||||
Invalid = 0,
|
||||
//can create accounts
|
||||
Administrator = 1,
|
||||
//has basic access
|
||||
User = 2,
|
||||
//authenticates but does not give access
|
||||
Restricted = 3,
|
||||
//refuses to authenticate but maintains records
|
||||
Disabled = 4,
|
||||
}
|
||||
public class UserType
|
||||
{
|
||||
public UserTypeEnum Id { get; set; }
|
||||
[MaxLength(26)]
|
||||
public string Name { get; set; }
|
||||
public ICollection<User> Users { get; set; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user