diff --git a/API/Controllers/AccountController.cs b/API/Controllers/AccountController.cs
index 3c25974ef..54d304dd6 100644
--- a/API/Controllers/AccountController.cs
+++ b/API/Controllers/AccountController.cs
@@ -78,6 +78,8 @@ namespace API.Controllers
user.LastActive = DateTime.Now;
_userRepository.Update(user);
await _userRepository.SaveAllAsync();
+
+ _logger.LogInformation($"{user.UserName} logged in at {user.LastActive}");
return new UserDto
{
diff --git a/API/Controllers/LibraryController.cs b/API/Controllers/LibraryController.cs
index b87e75cbf..64a259503 100644
--- a/API/Controllers/LibraryController.cs
+++ b/API/Controllers/LibraryController.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Threading.Tasks;
using API.DTOs;
using API.Entities;
@@ -35,6 +36,47 @@ namespace API.Controllers
_taskScheduler = taskScheduler;
_seriesRepository = seriesRepository;
}
+
+ ///
+ /// Creates a new Library. Upon library creation, adds new library to all Admin accounts.
+ ///
+ ///
+ ///
+ [Authorize(Policy = "RequireAdminRole")]
+ [HttpPost("create")]
+ public async Task AddLibrary(CreateLibraryDto createLibraryDto)
+ {
+ if (await _libraryRepository.LibraryExists(createLibraryDto.Name))
+ {
+ return BadRequest("Library name already exists. Please choose a unique name to the server.");
+ }
+
+ var admins = (await _userRepository.GetAdminUsersAsync()).ToList();
+
+ var library = new Library
+ {
+ Name = createLibraryDto.Name,
+ Type = createLibraryDto.Type,
+ AppUsers = admins,
+ Folders = createLibraryDto.Folders.Select(x => new FolderPath {Path = x}).ToList()
+ };
+
+ foreach (var admin in admins)
+ {
+ // If user is null, then set it
+ admin.Libraries ??= new List();
+ admin.Libraries.Add(library);
+ }
+
+
+ if (await _userRepository.SaveAllAsync())
+ {
+ //TODO: Enqueue scan library task
+ return Ok();
+ }
+
+ return BadRequest("There was a critical issue. Please try again.");
+ }
///
/// Returns a list of directories for a given path. If path is empty, returns root drives.
@@ -92,6 +134,7 @@ namespace API.Controllers
// We have to send a json encoded Library (aka a DTO) to the Background Job thread.
// Because we use EF, we have circular dependencies back to Library and it will crap out
+ // TODO: Refactor this to use libraryId and move Library call in method.
BackgroundJob.Enqueue(() => _directoryService.ScanLibrary(library));
return Ok();
}
@@ -106,7 +149,6 @@ namespace API.Controllers
public async Task>> GetSeriesForLibrary(int libraryId)
{
return Ok(await _seriesRepository.GetSeriesForLibraryIdAsync(libraryId));
-
}
}
}
\ No newline at end of file
diff --git a/API/Controllers/UsersController.cs b/API/Controllers/UsersController.cs
index a332c88c9..b860316df 100644
--- a/API/Controllers/UsersController.cs
+++ b/API/Controllers/UsersController.cs
@@ -22,47 +22,6 @@ namespace API.Controllers
_libraryRepository = libraryRepository;
}
- [Authorize(Policy = "RequireAdminRole")]
- [HttpPost("add-library")]
- public async Task AddLibrary(CreateLibraryDto createLibraryDto)
- {
- // NOTE: I think we should move this into library controller because it gets added to all admins
-
- var user = await _userRepository.GetUserByUsernameAsync(User.GetUsername());
-
- if (user == null) return BadRequest("Could not validate user");
-
-
- if (await _libraryRepository.LibraryExists(createLibraryDto.Name))
- {
- return BadRequest("Library name already exists. Please choose a unique name to the server.");
- }
-
- var library = new Library
- {
- Name = createLibraryDto.Name.ToLower(),
- Type = createLibraryDto.Type,
- AppUsers = new List() { user }
- };
-
- library.Folders = createLibraryDto.Folders.Select(x => new FolderPath
- {
- Path = x,
- Library = library
- }).ToList();
-
- user.Libraries ??= new List(); // If user is null, then set it
-
- user.Libraries.Add(library);
-
- if (await _userRepository.SaveAllAsync())
- {
- return Ok();
- }
-
- return BadRequest("Not implemented");
- }
-
[Authorize(Policy = "RequireAdminRole")]
[HttpDelete("delete-user")]
public async Task DeleteUser(string username)
diff --git a/API/DTOs/VolumeDto.cs b/API/DTOs/VolumeDto.cs
index 1753d4679..b3dab2834 100644
--- a/API/DTOs/VolumeDto.cs
+++ b/API/DTOs/VolumeDto.cs
@@ -5,7 +5,8 @@ namespace API.DTOs
public class VolumeDto
{
public int Id { get; set; }
- public string Number { get; set; }
+ public int Number { get; set; }
+ public string Name { get; set; }
public string CoverImage { get; set; }
public ICollection Files { get; set; }
}
diff --git a/API/Data/Migrations/20210102173326_VolumeNumberRefactor.Designer.cs b/API/Data/Migrations/20210102173326_VolumeNumberRefactor.Designer.cs
new file mode 100644
index 000000000..1102111fc
--- /dev/null
+++ b/API/Data/Migrations/20210102173326_VolumeNumberRefactor.Designer.cs
@@ -0,0 +1,512 @@
+//
+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("20210102173326_VolumeNumberRefactor")]
+ partial class VolumeNumberRefactor
+ {
+ 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("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property("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("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("AccessFailedCount")
+ .HasColumnType("INTEGER");
+
+ b.Property("ConcurrencyStamp")
+ .IsConcurrencyToken()
+ .HasColumnType("TEXT");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("Email")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property("EmailConfirmed")
+ .HasColumnType("INTEGER");
+
+ b.Property("IsAdmin")
+ .HasColumnType("INTEGER");
+
+ b.Property("LastActive")
+ .HasColumnType("TEXT");
+
+ b.Property("LockoutEnabled")
+ .HasColumnType("INTEGER");
+
+ b.Property("LockoutEnd")
+ .HasColumnType("TEXT");
+
+ b.Property("NormalizedEmail")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property("NormalizedUserName")
+ .HasMaxLength(256)
+ .HasColumnType("TEXT");
+
+ b.Property("PasswordHash")
+ .HasColumnType("TEXT");
+
+ b.Property("PhoneNumber")
+ .HasColumnType("TEXT");
+
+ b.Property("PhoneNumberConfirmed")
+ .HasColumnType("INTEGER");
+
+ b.Property("RowVersion")
+ .IsConcurrencyToken()
+ .HasColumnType("INTEGER");
+
+ b.Property("SecurityStamp")
+ .HasColumnType("TEXT");
+
+ b.Property("TwoFactorEnabled")
+ .HasColumnType("INTEGER");
+
+ b.Property("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.AppUserRole", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("INTEGER");
+
+ b.Property("RoleId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("UserId", "RoleId");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetUserRoles");
+ });
+
+ modelBuilder.Entity("API.Entities.FolderPath", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("LibraryId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Path")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LibraryId");
+
+ b.ToTable("FolderPath");
+ });
+
+ modelBuilder.Entity("API.Entities.Library", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CoverImage")
+ .HasColumnType("TEXT");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("LastModified")
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("Type")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("Library");
+ });
+
+ modelBuilder.Entity("API.Entities.MangaFile", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("FilePath")
+ .HasColumnType("TEXT");
+
+ b.Property("VolumeId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("VolumeId");
+
+ b.ToTable("MangaFile");
+ });
+
+ modelBuilder.Entity("API.Entities.Series", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CoverImage")
+ .HasColumnType("TEXT");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("LastModified")
+ .HasColumnType("TEXT");
+
+ b.Property("LibraryId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("OriginalName")
+ .HasColumnType("TEXT");
+
+ b.Property("SortName")
+ .HasColumnType("TEXT");
+
+ b.Property("Summary")
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LibraryId");
+
+ b.ToTable("Series");
+ });
+
+ modelBuilder.Entity("API.Entities.Volume", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Created")
+ .HasColumnType("TEXT");
+
+ b.Property("LastModified")
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("Number")
+ .HasColumnType("INTEGER");
+
+ b.Property("SeriesId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("SeriesId");
+
+ b.ToTable("Volume");
+ });
+
+ modelBuilder.Entity("AppUserLibrary", b =>
+ {
+ b.Property("AppUsersId")
+ .HasColumnType("INTEGER");
+
+ b.Property("LibrariesId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("AppUsersId", "LibrariesId");
+
+ b.HasIndex("LibrariesId");
+
+ b.ToTable("AppUserLibrary");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("ClaimType")
+ .HasColumnType("TEXT");
+
+ b.Property("ClaimValue")
+ .HasColumnType("TEXT");
+
+ b.Property("RoleId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RoleId");
+
+ b.ToTable("AspNetRoleClaims");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("ClaimType")
+ .HasColumnType("TEXT");
+
+ b.Property("ClaimValue")
+ .HasColumnType("TEXT");
+
+ b.Property("UserId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserClaims");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.Property("LoginProvider")
+ .HasColumnType("TEXT");
+
+ b.Property("ProviderKey")
+ .HasColumnType("TEXT");
+
+ b.Property("ProviderDisplayName")
+ .HasColumnType("TEXT");
+
+ b.Property("UserId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("LoginProvider", "ProviderKey");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("AspNetUserLogins");
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b =>
+ {
+ b.Property("UserId")
+ .HasColumnType("INTEGER");
+
+ b.Property("LoginProvider")
+ .HasColumnType("TEXT");
+
+ b.Property("Name")
+ .HasColumnType("TEXT");
+
+ b.Property("Value")
+ .HasColumnType("TEXT");
+
+ b.HasKey("UserId", "LoginProvider", "Name");
+
+ b.ToTable("AspNetUserTokens");
+ });
+
+ 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.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.Volume", "Volume")
+ .WithMany("Files")
+ .HasForeignKey("VolumeId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Volume");
+ });
+
+ 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", b =>
+ {
+ b.HasOne("API.Entities.AppRole", null)
+ .WithMany()
+ .HasForeignKey("RoleId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b =>
+ {
+ b.HasOne("API.Entities.AppUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b =>
+ {
+ b.HasOne("API.Entities.AppUser", null)
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", 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("UserRoles");
+ });
+
+ 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("Files");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/API/Data/Migrations/20210102173326_VolumeNumberRefactor.cs b/API/Data/Migrations/20210102173326_VolumeNumberRefactor.cs
new file mode 100644
index 000000000..21cc8d42c
--- /dev/null
+++ b/API/Data/Migrations/20210102173326_VolumeNumberRefactor.cs
@@ -0,0 +1,41 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace API.Data.Migrations
+{
+ public partial class VolumeNumberRefactor : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AlterColumn(
+ name: "Number",
+ table: "Volume",
+ type: "INTEGER",
+ nullable: false,
+ defaultValue: 0,
+ oldClrType: typeof(string),
+ oldType: "TEXT",
+ oldNullable: true);
+
+ migrationBuilder.AddColumn(
+ name: "Name",
+ table: "Volume",
+ type: "TEXT",
+ nullable: true);
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "Name",
+ table: "Volume");
+
+ migrationBuilder.AlterColumn(
+ name: "Number",
+ table: "Volume",
+ type: "TEXT",
+ nullable: true,
+ oldClrType: typeof(int),
+ oldType: "INTEGER");
+ }
+ }
+}
diff --git a/API/Data/Migrations/DataContextModelSnapshot.cs b/API/Data/Migrations/DataContextModelSnapshot.cs
index f840250c9..5b22f751d 100644
--- a/API/Data/Migrations/DataContextModelSnapshot.cs
+++ b/API/Data/Migrations/DataContextModelSnapshot.cs
@@ -249,9 +249,12 @@ namespace API.Data.Migrations
b.Property("LastModified")
.HasColumnType("TEXT");
- b.Property("Number")
+ b.Property("Name")
.HasColumnType("TEXT");
+ b.Property("Number")
+ .HasColumnType("INTEGER");
+
b.Property("SeriesId")
.HasColumnType("INTEGER");
diff --git a/API/Data/SeriesRepository.cs b/API/Data/SeriesRepository.cs
index fd109f45f..a9623275b 100644
--- a/API/Data/SeriesRepository.cs
+++ b/API/Data/SeriesRepository.cs
@@ -50,6 +50,7 @@ namespace API.Data
{
return await _context.Series
.Where(series => series.LibraryId == libraryId)
+ .OrderBy(s => s.SortName)
.ProjectTo(_mapper.ConfigurationProvider).ToListAsync();
}
@@ -57,6 +58,7 @@ namespace API.Data
{
return await _context.Volume
.Where(vol => vol.SeriesId == seriesId)
+ .OrderBy(volume => volume.Number)
.ProjectTo(_mapper.ConfigurationProvider).ToListAsync();
}
@@ -64,6 +66,7 @@ namespace API.Data
{
return _context.Volume
.Where(vol => vol.SeriesId == seriesId)
+ .OrderBy(vol => vol.Number)
.ProjectTo(_mapper.ConfigurationProvider).ToList();
}
@@ -71,6 +74,7 @@ namespace API.Data
{
return _context.Volume
.Where(vol => vol.SeriesId == seriesId)
+ .OrderBy(vol => vol.Number)
.ToList();
}
diff --git a/API/Data/UserRepository.cs b/API/Data/UserRepository.cs
index 6c63d31b9..5098b156c 100644
--- a/API/Data/UserRepository.cs
+++ b/API/Data/UserRepository.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using API.Constants;
using API.DTOs;
using API.Entities;
using API.Interfaces;
@@ -55,6 +56,11 @@ namespace API.Data
.SingleOrDefaultAsync(x => x.UserName == username);
}
+ public async Task> GetAdminUsersAsync()
+ {
+ return await _userManager.GetUsersInRoleAsync(PolicyConstants.AdminRole);
+ }
+
public async Task> GetMembersAsync()
{
return await _userManager.Users
diff --git a/API/Entities/AppUser.cs b/API/Entities/AppUser.cs
index ea7ad0245..f5b16890d 100644
--- a/API/Entities/AppUser.cs
+++ b/API/Entities/AppUser.cs
@@ -1,16 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using API.Entities.Interfaces;
using Microsoft.AspNetCore.Identity;
namespace API.Entities
{
- public class AppUser : IdentityUser
+ public class AppUser : IdentityUser, IHasConcurrencyToken
{
public DateTime Created { get; set; } = DateTime.Now;
public DateTime LastActive { get; set; }
- public bool IsAdmin { get; set; }
public ICollection Libraries { get; set; }
[ConcurrencyCheck]
diff --git a/API/Entities/Volume.cs b/API/Entities/Volume.cs
index 80d1f6573..18cadee8d 100644
--- a/API/Entities/Volume.cs
+++ b/API/Entities/Volume.cs
@@ -7,7 +7,8 @@ namespace API.Entities
public class Volume : IEntityDate
{
public int Id { get; set; }
- public string Number { get; set; }
+ public string Name { get; set; }
+ public int Number { get; set; }
public ICollection Files { get; set; }
public DateTime Created { get; set; }
public DateTime LastModified { get; set; }
diff --git a/API/Interfaces/IUserRepository.cs b/API/Interfaces/IUserRepository.cs
index 31be6e52e..26e3b5a11 100644
--- a/API/Interfaces/IUserRepository.cs
+++ b/API/Interfaces/IUserRepository.cs
@@ -15,5 +15,6 @@ namespace API.Interfaces
Task> GetMembersAsync();
Task GetMemberAsync(string username);
public void Delete(AppUser user);
+ Task> GetAdminUsersAsync();
}
}
\ No newline at end of file
diff --git a/API/Services/DirectoryService.cs b/API/Services/DirectoryService.cs
index f8ee643ce..9d40069e7 100644
--- a/API/Services/DirectoryService.cs
+++ b/API/Services/DirectoryService.cs
@@ -151,7 +151,7 @@ namespace API.Services
IList existingVolumes = _seriesRepository.GetVolumes(series.Id).ToList();
foreach (var info in infos)
{
- var existingVolume = existingVolumes.SingleOrDefault(v => v.Number == info.Volumes);
+ var existingVolume = existingVolumes.SingleOrDefault(v => v.Name == info.Volumes);
if (existingVolume != null)
{
// Temp let's overwrite all files (we need to enhance to update files)
@@ -168,7 +168,8 @@ namespace API.Services
{
var vol = new Volume()
{
- Number = info.Volumes,
+ Name = info.Volumes,
+ Number = Int32.Parse(info.Volumes),
Files = new List()
{
new MangaFile()