diff --git a/API/Controllers/AccountController.cs b/API/Controllers/AccountController.cs
index 01eb52412..62ad0ebb8 100644
--- a/API/Controllers/AccountController.cs
+++ b/API/Controllers/AccountController.cs
@@ -78,7 +78,6 @@ namespace API.Controllers
///
///
///
- [Authorize(Policy = "RequireAdminRole")]
[HttpPost("register")]
public async Task> Register(RegisterDto registerDto)
{
@@ -89,6 +88,17 @@ namespace API.Controllers
return BadRequest("Username is taken.");
}
+ // If we are registering an admin account, ensure there are no existing admins or user registering is an admin
+ if (registerDto.IsAdmin)
+ {
+ var firstTimeFlow = !(await _userManager.GetUsersInRoleAsync("Admin")).Any();
+ if (!firstTimeFlow && !await _unitOfWork.UserRepository.IsUserAdminAsync(
+ await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername())))
+ {
+ return BadRequest("You are not permitted to create an admin account");
+ }
+ }
+
var user = _mapper.Map(registerDto);
user.UserPreferences ??= new AppUserPreferences();
user.ApiKey = HashUtil.ApiKey();
@@ -104,6 +114,7 @@ namespace API.Controllers
if (!result.Succeeded) return BadRequest(result.Errors);
+
var role = registerDto.IsAdmin ? PolicyConstants.AdminRole : PolicyConstants.PlebRole;
var roleResult = await _userManager.AddToRoleAsync(user, role);
@@ -156,7 +167,7 @@ namespace API.Controllers
if (user == null) return Unauthorized("Invalid username");
- var isAdmin = await _unitOfWork.UserRepository.IsUserAdmin(user);
+ var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
var settings = await _unitOfWork.SettingsRepository.GetSettingsDtoAsync();
if (!settings.EnableAuthentication && !isAdmin)
{
diff --git a/API/Controllers/CollectionController.cs b/API/Controllers/CollectionController.cs
index 2b69499de..9f297273f 100644
--- a/API/Controllers/CollectionController.cs
+++ b/API/Controllers/CollectionController.cs
@@ -32,7 +32,7 @@ namespace API.Controllers
public async Task> GetAllTags()
{
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername());
- var isAdmin = await _unitOfWork.UserRepository.IsUserAdmin(user);
+ var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
if (isAdmin)
{
return await _unitOfWork.CollectionTagRepository.GetAllTagDtosAsync();
diff --git a/API/Controllers/OPDSController.cs b/API/Controllers/OPDSController.cs
index 68b9c14a2..7de25dcf3 100644
--- a/API/Controllers/OPDSController.cs
+++ b/API/Controllers/OPDSController.cs
@@ -184,7 +184,7 @@ public class OpdsController : BaseApiController
return BadRequest("OPDS is not enabled on this server");
var userId = await GetUser(apiKey);
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
- var isAdmin = await _unitOfWork.UserRepository.IsUserAdmin(user);
+ var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
IList tags = isAdmin ? (await _unitOfWork.CollectionTagRepository.GetAllTagDtosAsync()).ToList()
: (await _unitOfWork.CollectionTagRepository.GetAllPromotedTagDtosAsync()).ToList();
@@ -220,7 +220,7 @@ public class OpdsController : BaseApiController
return BadRequest("OPDS is not enabled on this server");
var userId = await GetUser(apiKey);
var user = await _unitOfWork.UserRepository.GetUserByIdAsync(userId);
- var isAdmin = await _unitOfWork.UserRepository.IsUserAdmin(user);
+ var isAdmin = await _unitOfWork.UserRepository.IsUserAdminAsync(user);
IEnumerable tags;
if (isAdmin)
diff --git a/API/Controllers/SeriesController.cs b/API/Controllers/SeriesController.cs
index bf7de16e7..ec63e3b3e 100644
--- a/API/Controllers/SeriesController.cs
+++ b/API/Controllers/SeriesController.cs
@@ -154,7 +154,7 @@ namespace API.Controllers
public async Task UpdateSeriesRating(UpdateSeriesRatingDto updateSeriesRatingDto)
{
var user = await _unitOfWork.UserRepository.GetUserByUsernameAsync(User.GetUsername(), AppUserIncludes.Ratings);
- var userRating = await _unitOfWork.UserRepository.GetUserRating(updateSeriesRatingDto.SeriesId, user.Id) ??
+ var userRating = await _unitOfWork.UserRepository.GetUserRatingAsync(updateSeriesRatingDto.SeriesId, user.Id) ??
new AppUserRating();
userRating.Rating = updateSeriesRatingDto.UserRating;
diff --git a/API/Data/Repositories/UserRepository.cs b/API/Data/Repositories/UserRepository.cs
index 2b3bfd478..138ef15b8 100644
--- a/API/Data/Repositories/UserRepository.cs
+++ b/API/Data/Repositories/UserRepository.cs
@@ -32,8 +32,8 @@ public interface IUserRepository
Task> GetMembersAsync();
Task> GetAdminUsersAsync();
Task> GetNonAdminUsersAsync();
- Task IsUserAdmin(AppUser user);
- Task GetUserRating(int seriesId, int userId);
+ Task IsUserAdminAsync(AppUser user);
+ Task GetUserRatingAsync(int seriesId, int userId);
Task GetPreferencesAsync(string username);
Task> GetBookmarkDtosForSeries(int userId, int seriesId);
Task> GetBookmarkDtosForVolume(int userId, int volumeId);
@@ -208,12 +208,12 @@ public class UserRepository : IUserRepository
return await _userManager.GetUsersInRoleAsync(PolicyConstants.PlebRole);
}
- public async Task IsUserAdmin(AppUser user)
+ public async Task IsUserAdminAsync(AppUser user)
{
return await _userManager.IsInRoleAsync(user, PolicyConstants.AdminRole);
}
- public async Task GetUserRating(int seriesId, int userId)
+ public async Task GetUserRatingAsync(int seriesId, int userId)
{
return await _context.AppUserRating.Where(r => r.SeriesId == seriesId && r.AppUserId == userId)
.SingleOrDefaultAsync();
diff --git a/API/Program.cs b/API/Program.cs
index 713e2c404..73b9b5b7f 100644
--- a/API/Program.cs
+++ b/API/Program.cs
@@ -56,51 +56,29 @@ namespace API
try
{
+ var logger = services.GetRequiredService>();
var context = services.GetRequiredService();
+ var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
+ if (pendingMigrations.Any())
+ {
+ logger.LogInformation("Performing backup as migrations are needed. Backup will be kavita.db in temp folder");
+ directoryService.CopyFileToDirectory(directoryService.FileSystem.Path.Join(directoryService.ConfigDirectory, "kavita.db"), directoryService.TempDirectory);
+ }
+
+ await context.Database.MigrateAsync();
+ var roleManager = services.GetRequiredService>();
+
+ await Seed.SeedRoles(roleManager);
+ await Seed.SeedSettings(context, directoryService);
+ await Seed.SeedUserApiKeys(context);
if (isDocker && new FileInfo("data/appsettings.json").Exists)
{
- var logger = services.GetRequiredService>();
+ //var logger = services.GetRequiredService>();
logger.LogCritical("WARNING! Mount point is incorrect, nothing here will persist. Please change your container mount from /kavita/data to /kavita/config");
return;
}
-
- var requiresCoverImageMigration = !Directory.Exists(directoryService.CoverImageDirectory);
- try
- {
- // If this is a new install, tables wont exist yet
- if (requiresCoverImageMigration)
- {
- MigrateCoverImages.ExtractToImages(context, directoryService, services.GetRequiredService());
- }
- }
- catch (Exception)
- {
- requiresCoverImageMigration = false;
- }
-
- if (requiresCoverImageMigration)
- {
- await MigrateCoverImages.UpdateDatabaseWithImages(context, directoryService);
- }
-
- // // Apply all migrations on startup
- // // If we have pending migrations, make a backup first
- // var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
- // if (pendingMigrations.Any())
- // {
- // var logger = services.GetRequiredService>();
- // logger.LogInformation("Performing backup as migrations are needed");
- // // var backupService = services.GetRequiredService();
- // // await backupService.BackupDatabase();
- // }
- //
- // await context.Database.MigrateAsync();
- //
- // await Seed.SeedRoles(roleManager);
- // await Seed.SeedSettings(context, directoryService);
- // await Seed.SeedUserApiKeys(context);
}
catch (Exception ex)
{
diff --git a/API/Startup.cs b/API/Startup.cs
index b6bd5630e..f7eb31aee 100644
--- a/API/Startup.cs
+++ b/API/Startup.cs
@@ -134,7 +134,7 @@ namespace API
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IBackgroundJobClient backgroundJobs, IWebHostEnvironment env,
IHostApplicationLifetime applicationLifetime, IServiceProvider serviceProvider, ICacheService cacheService,
- IDirectoryService directoryService, IUnitOfWork unitOfWork, IBackupService backupService)
+ IDirectoryService directoryService, IUnitOfWork unitOfWork, IBackupService backupService, IImageService imageService)
{
// Apply Migrations
@@ -144,26 +144,44 @@ namespace API
{
// Apply all migrations on startup
// If we have pending migrations, make a backup first
+ var isDocker = new OsInfo(Array.Empty()).IsDocker;
var logger = serviceProvider.GetRequiredService>();
var context = serviceProvider.GetRequiredService();
- var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
- if (pendingMigrations.Any())
- {
- logger.LogInformation("Performing backup as migrations are needed");
- await backupService.BackupDatabase();
- }
-
- await context.Database.MigrateAsync();
+ // var pendingMigrations = await context.Database.GetPendingMigrationsAsync();
+ // if (pendingMigrations.Any())
+ // {
+ // logger.LogInformation("Performing backup as migrations are needed");
+ // await backupService.BackupDatabase();
+ // }
+ //
+ // await context.Database.MigrateAsync();
+ // var roleManager = serviceProvider.GetRequiredService>();
+ //
+ // await Seed.SeedRoles(roleManager);
+ // await Seed.SeedSettings(context, directoryService);
+ // await Seed.SeedUserApiKeys(context);
await MigrateBookmarks.Migrate(directoryService, unitOfWork,
logger, cacheService);
- var roleManager = serviceProvider.GetRequiredService>();
-
- await Seed.SeedRoles(roleManager);
- await Seed.SeedSettings(context, directoryService);
- await Seed.SeedUserApiKeys(context);
+ var requiresCoverImageMigration = !Directory.Exists(directoryService.CoverImageDirectory);
+ try
+ {
+ // If this is a new install, tables wont exist yet
+ if (requiresCoverImageMigration)
+ {
+ MigrateCoverImages.ExtractToImages(context, directoryService, imageService);
+ }
+ }
+ catch (Exception)
+ {
+ requiresCoverImageMigration = false;
+ }
+ if (requiresCoverImageMigration)
+ {
+ await MigrateCoverImages.UpdateDatabaseWithImages(context, directoryService);
+ }
}).GetAwaiter()
.GetResult();
}