mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
Merge pull request #49 from Kareadita/feature/settings-continued
User Preferences
This commit is contained in:
commit
b30560fdda
@ -1,18 +1,10 @@
|
||||
using API.Helpers.Converters;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace API.Tests.Converters
|
||||
{
|
||||
public class CronConverterTests
|
||||
{
|
||||
private readonly ITestOutputHelper _testOutputHelper;
|
||||
|
||||
public CronConverterTests(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
_testOutputHelper = testOutputHelper;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("daily", "0 0 * * *")]
|
||||
[InlineData("disabled", "0 0 31 2 *")]
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Parser;
|
||||
using Xunit;
|
||||
using static API.Parser.Parser;
|
||||
@ -109,7 +109,10 @@ namespace API.Tests
|
||||
[InlineData("Yumekui-Merry_DKThias_Chapter21.zip", "21")]
|
||||
[InlineData("Yumekui_Merry_v01_c01[Bakayarou-Kuu].rar", "1")]
|
||||
[InlineData("Yumekui-Merry_DKThias_Chapter11v2.zip", "11")]
|
||||
[InlineData("Yumekui-Merry DKThiasScanlations Chapter51v2", "51")]
|
||||
[InlineData("Goblin Slayer Side Story - Year One 017.5", "17.5")]
|
||||
[InlineData("Beelzebub_53[KSH].zip", "53")]
|
||||
[InlineData("Black Bullet - v4 c20.5 [batoto]", "20.5")]
|
||||
//[InlineData("[Tempus Edax Rerum] Epigraph of the Closed Curve - Chapter 6.zip", "6")]
|
||||
public void ParseChaptersTest(string filename, string expected)
|
||||
{
|
||||
|
@ -1,8 +1,4 @@
|
||||
using API.Interfaces;
|
||||
using API.Services;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
using Xunit;
|
||||
|
||||
namespace API.Tests.Services
|
||||
{
|
||||
|
@ -63,6 +63,7 @@ namespace API.Controllers
|
||||
}
|
||||
|
||||
var user = _mapper.Map<AppUser>(registerDto);
|
||||
user.UserPreferences ??= new AppUserPreferences();
|
||||
|
||||
var result = await _userManager.CreateAsync(user, registerDto.Password);
|
||||
|
||||
@ -83,13 +84,14 @@ namespace API.Controllers
|
||||
lib.AppUsers ??= new List<AppUser>();
|
||||
lib.AppUsers.Add(user);
|
||||
}
|
||||
if (libraries.Any() && !await _unitOfWork.Complete()) _logger.LogInformation("There was an issue granting library access. Please do this manually.");
|
||||
if (libraries.Any() && !await _unitOfWork.Complete()) _logger.LogError("There was an issue granting library access. Please do this manually.");
|
||||
}
|
||||
|
||||
return new UserDto
|
||||
{
|
||||
Username = user.UserName,
|
||||
Token = await _tokenService.CreateToken(user),
|
||||
Preferences = _mapper.Map<UserPreferencesDto>(user.UserPreferences)
|
||||
};
|
||||
}
|
||||
|
||||
@ -97,11 +99,12 @@ namespace API.Controllers
|
||||
public async Task<ActionResult<UserDto>> Login(LoginDto loginDto)
|
||||
{
|
||||
var user = await _userManager.Users
|
||||
.Include(u => u.UserPreferences)
|
||||
.SingleOrDefaultAsync(x => x.NormalizedUserName == loginDto.Username.ToUpper());
|
||||
|
||||
var debugUsers = await _userManager.Users.Select(x => x.NormalizedUserName).ToListAsync();
|
||||
|
||||
_logger.LogInformation($"All Users: {String.Join(",", debugUsers)}");
|
||||
_logger.LogInformation($"All Users: {string.Join(",", debugUsers)}");
|
||||
|
||||
if (user == null) return Unauthorized("Invalid username");
|
||||
|
||||
@ -112,6 +115,8 @@ namespace API.Controllers
|
||||
|
||||
// Update LastActive on account
|
||||
user.LastActive = DateTime.Now;
|
||||
user.UserPreferences ??= new AppUserPreferences();
|
||||
|
||||
_unitOfWork.UserRepository.Update(user);
|
||||
await _unitOfWork.Complete();
|
||||
|
||||
@ -120,7 +125,8 @@ namespace API.Controllers
|
||||
return new UserDto
|
||||
{
|
||||
Username = user.UserName,
|
||||
Token = await _tokenService.CreateToken(user)
|
||||
Token = await _tokenService.CreateToken(user),
|
||||
Preferences = _mapper.Map<UserPreferencesDto>(user.UserPreferences)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
30
API/Controllers/ServerController.cs
Normal file
30
API/Controllers/ServerController.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using API.Extensions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace API.Controllers
|
||||
{
|
||||
[Authorize(Policy = "RequireAdminRole")]
|
||||
public class ServerController : BaseApiController
|
||||
{
|
||||
private readonly IHostApplicationLifetime _applicationLifetime;
|
||||
private readonly ILogger<ServerController> _logger;
|
||||
|
||||
public ServerController(IHostApplicationLifetime applicationLifetime, ILogger<ServerController> logger)
|
||||
{
|
||||
_applicationLifetime = applicationLifetime;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
[HttpPost("restart")]
|
||||
public ActionResult RestartServer()
|
||||
{
|
||||
_logger.LogInformation($"{User.GetUsername()} is restarting server from admin dashboard.");
|
||||
|
||||
_applicationLifetime.StopApplication();
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Extensions;
|
||||
using API.Helpers.Converters;
|
||||
using API.Interfaces;
|
||||
@ -62,6 +63,13 @@ namespace API.Controllers
|
||||
setting.Value = updateSettingsDto.TaskScan;
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.Port && updateSettingsDto.Port + "" != setting.Value)
|
||||
{
|
||||
setting.Value = updateSettingsDto.Port + "";
|
||||
Environment.SetEnvironmentVariable("KAVITA_PORT", setting.Value);
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
}
|
||||
|
||||
if (_unitOfWork.HasChanges() && await _unitOfWork.Complete())
|
||||
|
@ -44,5 +44,25 @@ namespace API.Controllers
|
||||
var libs = await _unitOfWork.LibraryRepository.GetLibraryDtosForUsernameAsync(User.GetUsername());
|
||||
return Ok(libs.Any(x => x.Id == libraryId));
|
||||
}
|
||||
|
||||
[HttpPost("update-preferences")]
|
||||
public async Task<ActionResult<UserPreferencesDto>> UpdatePreferences(UserPreferencesDto preferencesDto)
|
||||
{
|
||||
var existingPreferences = await _unitOfWork.UserRepository.GetPreferencesAsync(User.GetUsername());
|
||||
|
||||
existingPreferences.ReadingDirection = preferencesDto.ReadingDirection;
|
||||
existingPreferences.ScalingOption = preferencesDto.ScalingOption;
|
||||
existingPreferences.PageSplitOption = preferencesDto.PageSplitOption;
|
||||
existingPreferences.HideReadOnDetails = preferencesDto.HideReadOnDetails;
|
||||
|
||||
_unitOfWork.UserRepository.Update(existingPreferences);
|
||||
|
||||
if (await _unitOfWork.Complete())
|
||||
{
|
||||
return Ok(preferencesDto);
|
||||
}
|
||||
|
||||
return BadRequest("There was an issue saving preferences.");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.DTOs
|
||||
{
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.DTOs
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.DTOs
|
||||
{
|
||||
|
@ -6,5 +6,6 @@
|
||||
public string TaskScan { get; set; }
|
||||
public string LoggingLevel { get; set; }
|
||||
public string TaskBackup { get; set; }
|
||||
public int Port { get; set; }
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
namespace API.DTOs
|
||||
|
||||
namespace API.DTOs
|
||||
{
|
||||
public class UserDto
|
||||
{
|
||||
public string Username { get; init; }
|
||||
public string Token { get; init; }
|
||||
public UserPreferencesDto Preferences { get; set; }
|
||||
}
|
||||
}
|
15
API/DTOs/UserPreferencesDto.cs
Normal file
15
API/DTOs/UserPreferencesDto.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.DTOs
|
||||
{
|
||||
public class UserPreferencesDto
|
||||
{
|
||||
public ReadingDirection ReadingDirection { get; set; }
|
||||
public ScalingOption ScalingOption { get; set; }
|
||||
public PageSplitOption PageSplitOption { get; set; }
|
||||
/// <summary>
|
||||
/// Whether UI hides read Volumes on Details page
|
||||
/// </summary>
|
||||
public bool HideReadOnDetails { get; set; }
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace API.DTOs
|
||||
@ -11,6 +12,9 @@ namespace API.DTOs
|
||||
public byte[] CoverImage { get; set; }
|
||||
public int Pages { get; set; }
|
||||
public int PagesRead { get; set; }
|
||||
public DateTime LastModified { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
public bool IsSpecial { get; set; }
|
||||
public ICollection<ChapterDto> Chapters { get; set; }
|
||||
}
|
||||
}
|
@ -28,6 +28,7 @@ namespace API.Data
|
||||
public DbSet<AppUserProgress> AppUserProgresses { get; set; }
|
||||
public DbSet<AppUserRating> AppUserRating { get; set; }
|
||||
public DbSet<ServerSetting> ServerSetting { get; set; }
|
||||
public DbSet<AppUserPreferences> AppUserPreferences { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
|
718
API/Data/Migrations/20210205220227_UserPreferences.Designer.cs
generated
Normal file
718
API/Data/Migrations/20210205220227_UserPreferences.Designer.cs
generated
Normal file
@ -0,0 +1,718 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using API.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
|
||||
namespace API.Data.Migrations
|
||||
{
|
||||
[DbContext(typeof(DataContext))]
|
||||
[Migration("20210205220227_UserPreferences")]
|
||||
partial class UserPreferences
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "5.0.1");
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppRole", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUser", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AccessFailedCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("EmailConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastActive")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("LockoutEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("PhoneNumber")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SecurityStamp")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256)
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasDatabaseName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("HideReadOnDetails")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("PageSplitOption")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ReadingDirection")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ScalingOption")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AppUserPreferences");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserProgress", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ChapterId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("PagesRead")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeriesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("VolumeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("AppUserProgresses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserRating", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Rating")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Review")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("SeriesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId");
|
||||
|
||||
b.ToTable("AppUserRating");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserRole", b =>
|
||||
{
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("RoleId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Chapter", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("CoverImage")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Number")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Pages")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Range")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("VolumeId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("VolumeId");
|
||||
|
||||
b.ToTable("Chapter");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.FolderPath", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastScanned")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("LibraryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Path")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LibraryId");
|
||||
|
||||
b.ToTable("FolderPath");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Library", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("CoverImage")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Type")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Library");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.MangaFile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ChapterId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("FilePath")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Format")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("NumberOfPages")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ChapterId");
|
||||
|
||||
b.ToTable("MangaFile");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Series", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("CoverImage")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("LibraryId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("OriginalName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Pages")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("SortName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Summary")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LibraryId");
|
||||
|
||||
b.ToTable("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.ServerSetting", b =>
|
||||
{
|
||||
b.Property<int>("Key")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<uint>("RowVersion")
|
||||
.IsConcurrencyToken()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Key");
|
||||
|
||||
b.ToTable("ServerSetting");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Volume", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<byte[]>("CoverImage")
|
||||
.HasColumnType("BLOB");
|
||||
|
||||
b.Property<DateTime>("Created")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("IsSpecial")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime>("LastModified")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("Number")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Pages")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("SeriesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("SeriesId");
|
||||
|
||||
b.ToTable("Volume");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AppUserLibrary", b =>
|
||||
{
|
||||
b.Property<int>("AppUsersId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("LibrariesId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("AppUsersId", "LibrariesId");
|
||||
|
||||
b.HasIndex("LibrariesId");
|
||||
|
||||
b.ToTable("AppUserLibrary");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("RoleId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("ClaimType")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ClaimValue")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderKey")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("ProviderDisplayName")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
||||
{
|
||||
b.Property<int>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("LoginProvider")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithOne("UserPreferences")
|
||||
.HasForeignKey("API.Entities.AppUserPreferences", "AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserProgress", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithMany("Progresses")
|
||||
.HasForeignKey("AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserRating", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithMany("Ratings")
|
||||
.HasForeignKey("AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserRole", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppRole", "Role")
|
||||
.WithMany("UserRoles")
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("API.Entities.AppUser", "User")
|
||||
.WithMany("UserRoles")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Role");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Chapter", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Volume", "Volume")
|
||||
.WithMany("Chapters")
|
||||
.HasForeignKey("VolumeId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Volume");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.FolderPath", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Library", "Library")
|
||||
.WithMany("Folders")
|
||||
.HasForeignKey("LibraryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Library");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.MangaFile", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Chapter", "Chapter")
|
||||
.WithMany("Files")
|
||||
.HasForeignKey("ChapterId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Chapter");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Series", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Library", "Library")
|
||||
.WithMany("Series")
|
||||
.HasForeignKey("LibraryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Library");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Volume", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.Series", "Series")
|
||||
.WithMany("Volumes")
|
||||
.HasForeignKey("SeriesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("AppUserLibrary", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("AppUsersId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("API.Entities.Library", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("LibrariesId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<int>", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppRole", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<int>", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<int>", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<int>", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", null)
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppRole", b =>
|
||||
{
|
||||
b.Navigation("UserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUser", b =>
|
||||
{
|
||||
b.Navigation("Progresses");
|
||||
|
||||
b.Navigation("Ratings");
|
||||
|
||||
b.Navigation("UserPreferences");
|
||||
|
||||
b.Navigation("UserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Chapter", b =>
|
||||
{
|
||||
b.Navigation("Files");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Library", b =>
|
||||
{
|
||||
b.Navigation("Folders");
|
||||
|
||||
b.Navigation("Series");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Series", b =>
|
||||
{
|
||||
b.Navigation("Volumes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.Volume", b =>
|
||||
{
|
||||
b.Navigation("Chapters");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
45
API/Data/Migrations/20210205220227_UserPreferences.cs
Normal file
45
API/Data/Migrations/20210205220227_UserPreferences.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace API.Data.Migrations
|
||||
{
|
||||
public partial class UserPreferences : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AppUserPreferences",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
ReadingDirection = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
ScalingOption = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
PageSplitOption = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
HideReadOnDetails = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||
AppUserId = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AppUserPreferences", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AppUserPreferences_AspNetUsers_AppUserId",
|
||||
column: x => x.AppUserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AppUserPreferences_AppUserId",
|
||||
table: "AppUserPreferences",
|
||||
column: "AppUserId",
|
||||
unique: true);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AppUserPreferences");
|
||||
}
|
||||
}
|
||||
}
|
@ -118,6 +118,35 @@ namespace API.Data.Migrations
|
||||
b.ToTable("AspNetUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("AppUserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("HideReadOnDetails")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("PageSplitOption")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ReadingDirection")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("ScalingOption")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AppUserId")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("AppUserPreferences");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserProgress", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
@ -486,6 +515,17 @@ namespace API.Data.Migrations
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserPreferences", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
.WithOne("UserPreferences")
|
||||
.HasForeignKey("API.Entities.AppUserPreferences", "AppUserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("AppUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("API.Entities.AppUserProgress", b =>
|
||||
{
|
||||
b.HasOne("API.Entities.AppUser", "AppUser")
|
||||
@ -644,6 +684,8 @@ namespace API.Data.Migrations
|
||||
|
||||
b.Navigation("Ratings");
|
||||
|
||||
b.Navigation("UserPreferences");
|
||||
|
||||
b.Navigation("UserRoles");
|
||||
});
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Constants;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Services;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
|
||||
@ -30,12 +31,15 @@ namespace API.Data
|
||||
|
||||
public static async Task SeedSettings(DataContext context)
|
||||
{
|
||||
context.Database.EnsureCreated();
|
||||
await context.Database.EnsureCreatedAsync();
|
||||
|
||||
IList<ServerSetting> defaultSettings = new List<ServerSetting>()
|
||||
{
|
||||
new() {Key = ServerSettingKey.CacheDirectory, Value = CacheService.CacheDirectory},
|
||||
new () {Key = ServerSettingKey.TaskScan, Value = "daily"}
|
||||
new () {Key = ServerSettingKey.TaskScan, Value = "daily"},
|
||||
//new () {Key = ServerSettingKey.LoggingLevel, Value = "Information"},
|
||||
//new () {Key = ServerSettingKey.TaskBackup, Value = "daily"},
|
||||
new () {Key = ServerSettingKey.Port, Value = "5000"},
|
||||
};
|
||||
|
||||
foreach (var defaultSetting in defaultSettings)
|
||||
@ -43,7 +47,7 @@ namespace API.Data
|
||||
var existing = context.ServerSetting.FirstOrDefault(s => s.Key == defaultSetting.Key);
|
||||
if (existing == null)
|
||||
{
|
||||
context.ServerSetting.Add(defaultSetting);
|
||||
await context.ServerSetting.AddAsync(defaultSetting);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Interfaces;
|
||||
using AutoMapper;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
@ -26,6 +26,11 @@ namespace API.Data
|
||||
_context.Entry(user).State = EntityState.Modified;
|
||||
}
|
||||
|
||||
public void Update(AppUserPreferences preferences)
|
||||
{
|
||||
_context.Entry(preferences).State = EntityState.Modified;
|
||||
}
|
||||
|
||||
public void Delete(AppUser user)
|
||||
{
|
||||
_context.AppUser.Remove(user);
|
||||
@ -59,6 +64,13 @@ namespace API.Data
|
||||
_context.AppUserRating.Add(userRating);
|
||||
}
|
||||
|
||||
public async Task<AppUserPreferences> GetPreferencesAsync(string username)
|
||||
{
|
||||
return await _context.AppUserPreferences
|
||||
.Include(p => p.AppUser)
|
||||
.SingleOrDefaultAsync(p => p.AppUser.UserName == username);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<MemberDto>> GetMembersAsync()
|
||||
{
|
||||
return await _context.Users
|
||||
|
@ -15,6 +15,7 @@ namespace API.Entities
|
||||
public ICollection<AppUserRole> UserRoles { get; set; }
|
||||
public ICollection<AppUserProgress> Progresses { get; set; }
|
||||
public ICollection<AppUserRating> Ratings { get; set; }
|
||||
public AppUserPreferences UserPreferences { get; set; }
|
||||
|
||||
[ConcurrencyCheck]
|
||||
public uint RowVersion { get; set; }
|
||||
|
21
API/Entities/AppUserPreferences.cs
Normal file
21
API/Entities/AppUserPreferences.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.Entities
|
||||
{
|
||||
public class AppUserPreferences
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public ReadingDirection ReadingDirection { get; set; } = ReadingDirection.LeftToRight;
|
||||
public ScalingOption ScalingOption { get; set; } = ScalingOption.FitToHeight;
|
||||
public PageSplitOption PageSplitOption { get; set; } = PageSplitOption.SplitRightToLeft;
|
||||
/// <summary>
|
||||
/// Whether UI hides read Volumes on Details page
|
||||
/// </summary>
|
||||
public bool HideReadOnDetails { get; set; } = false;
|
||||
|
||||
|
||||
|
||||
public AppUser AppUser { get; set; }
|
||||
public int AppUserId { get; set; }
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities.Enums
|
||||
{
|
||||
public enum LibraryType
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace API.Entities
|
||||
namespace API.Entities.Enums
|
||||
{
|
||||
public enum MangaFormat
|
||||
{
|
9
API/Entities/Enums/PageSplitOption.cs
Normal file
9
API/Entities/Enums/PageSplitOption.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace API.Entities.Enums
|
||||
{
|
||||
public enum PageSplitOption
|
||||
{
|
||||
SplitLeftToRight = 0,
|
||||
SplitRightToLeft = 1,
|
||||
NoSplit = 2
|
||||
}
|
||||
}
|
8
API/Entities/Enums/ReadingDirection.cs
Normal file
8
API/Entities/Enums/ReadingDirection.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace API.Entities.Enums
|
||||
{
|
||||
public enum ReadingDirection
|
||||
{
|
||||
LeftToRight = 0,
|
||||
RightToLeft = 1
|
||||
}
|
||||
}
|
9
API/Entities/Enums/ScalingOption.cs
Normal file
9
API/Entities/Enums/ScalingOption.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace API.Entities.Enums
|
||||
{
|
||||
public enum ScalingOption
|
||||
{
|
||||
FitToHeight = 0,
|
||||
FitToWidth = 1,
|
||||
Original = 2
|
||||
}
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
namespace API.Entities
|
||||
namespace API.Entities.Enums
|
||||
{
|
||||
public enum ServerSettingKey
|
||||
{
|
||||
TaskScan = 0,
|
||||
CacheDirectory = 1,
|
||||
TaskBackup = 2,
|
||||
LoggingLevel = 3
|
||||
LoggingLevel = 3,
|
||||
Port = 4
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using API.Entities.Enums;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.Entities
|
||||
|
@ -1,4 +1,6 @@
|
||||
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.Entities
|
||||
{
|
||||
public class MangaFile
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using API.Entities.Enums;
|
||||
using API.Entities.Interfaces;
|
||||
|
||||
namespace API.Entities
|
||||
|
@ -21,6 +21,8 @@ namespace API.Helpers
|
||||
|
||||
CreateMap<Series, SeriesDto>();
|
||||
|
||||
CreateMap<AppUserPreferences, UserPreferencesDto>();
|
||||
|
||||
CreateMap<Library, LibraryDto>()
|
||||
.ForMember(dest => dest.Folders,
|
||||
opt =>
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using AutoMapper;
|
||||
|
||||
namespace API.Helpers.Converters
|
||||
@ -26,7 +27,9 @@ namespace API.Helpers.Converters
|
||||
case ServerSettingKey.TaskBackup:
|
||||
destination.TaskBackup = row.Value;
|
||||
break;
|
||||
|
||||
case ServerSettingKey.Port:
|
||||
destination.Port = int.Parse(row.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Threading.Tasks;
|
||||
using API.DTOs;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.Interfaces
|
||||
{
|
||||
|
@ -8,11 +8,13 @@ namespace API.Interfaces
|
||||
public interface IUserRepository
|
||||
{
|
||||
void Update(AppUser user);
|
||||
void Update(AppUserPreferences preferences);
|
||||
public void Delete(AppUser user);
|
||||
Task<AppUser> GetUserByUsernameAsync(string username);
|
||||
Task<IEnumerable<MemberDto>> GetMembersAsync();
|
||||
Task<IEnumerable<AppUser>> GetAdminUsersAsync();
|
||||
Task<AppUserRating> GetUserRating(int seriesId, int userId);
|
||||
void AddRatingTracking(AppUserRating userRating);
|
||||
Task<AppUserPreferences> GetPreferencesAsync(string username);
|
||||
}
|
||||
}
|
@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.Parser
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
|
||||
namespace API.Parser
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ namespace API
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
private static readonly int HttpPort = 5000;
|
||||
protected Program()
|
||||
{
|
||||
}
|
||||
@ -46,7 +47,40 @@ namespace API
|
||||
Host.CreateDefaultBuilder(args)
|
||||
.ConfigureWebHostDefaults(webBuilder =>
|
||||
{
|
||||
webBuilder.UseKestrel((opts) =>
|
||||
{
|
||||
opts.ListenAnyIP(HttpPort);
|
||||
});
|
||||
webBuilder.UseStartup<Startup>();
|
||||
});
|
||||
|
||||
// private static void StartNewInstance()
|
||||
// {
|
||||
// //_logger.LogInformation("Starting new instance");
|
||||
//
|
||||
// var module = options.RestartPath;
|
||||
//
|
||||
// if (string.IsNullOrWhiteSpace(module))
|
||||
// {
|
||||
// module = Environment.GetCommandLineArgs()[0];
|
||||
// }
|
||||
//
|
||||
// // string commandLineArgsString;
|
||||
// // if (options.RestartArgs != null)
|
||||
// // {
|
||||
// // commandLineArgsString = options.RestartArgs ?? string.Empty;
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // commandLineArgsString = string.Join(
|
||||
// // ' ',
|
||||
// // Environment.GetCommandLineArgs().Skip(1).Select(NormalizeCommandLineArgument));
|
||||
// // }
|
||||
//
|
||||
// //_logger.LogInformation("Executable: {0}", module);
|
||||
// //_logger.LogInformation("Arguments: {0}", commandLineArgsString);
|
||||
//
|
||||
// Process.Start(module, Array.Empty<string>);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -129,6 +129,7 @@ namespace API.Services
|
||||
try {
|
||||
// TODO: In future, we need to take LibraryType into consideration for what extensions to allow (RAW should allow images)
|
||||
// or we need to move this filtering to another area (Process)
|
||||
// or we can get all files and put a check in place during Process to abandon files
|
||||
files = GetFilesWithCertainExtensions(currentDir, Parser.Parser.MangaFileExtensions)
|
||||
.ToArray();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Interfaces;
|
||||
using API.Parser;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
@ -1,5 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using API.Entities;
|
||||
using API.Entities.Enums;
|
||||
using API.Helpers.Converters;
|
||||
using API.Interfaces;
|
||||
using Hangfire;
|
||||
|
@ -3,6 +3,7 @@ using API.Middleware;
|
||||
using Hangfire;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -26,6 +27,11 @@ namespace API
|
||||
|
||||
services.AddApplicationServices(_config);
|
||||
services.AddControllers();
|
||||
services.Configure<ForwardedHeadersOptions>(options =>
|
||||
{
|
||||
options.ForwardedHeaders =
|
||||
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
|
||||
});
|
||||
services.AddCors();
|
||||
services.AddIdentityServices(_config);
|
||||
services.AddSwaggerGen(c =>
|
||||
@ -46,10 +52,15 @@ namespace API
|
||||
app.UseHangfireDashboard();
|
||||
}
|
||||
|
||||
app.UseForwardedHeaders();
|
||||
|
||||
app.UseRouting();
|
||||
|
||||
// Ordering is important. Cors, authentication, authorization
|
||||
app.UseCors(policy => policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:4200"));
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseCors(policy => policy.AllowAnyHeader().AllowAnyMethod().WithOrigins("http://localhost:4200"));
|
||||
}
|
||||
|
||||
app.UseAuthentication();
|
||||
|
||||
@ -62,6 +73,7 @@ namespace API
|
||||
ContentTypeProvider = new FileExtensionContentTypeProvider() // this is not set by default
|
||||
});
|
||||
|
||||
|
||||
app.UseEndpoints(endpoints =>
|
||||
{
|
||||
endpoints.MapControllers();
|
||||
|
Loading…
x
Reference in New Issue
Block a user