using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Moonlight.Api.Database; using Moonlight.Api.Database.Entities; using Moonlight.Api.Services; using Moonlight.Shared; using Moonlight.Shared.Http.Requests.Seup; namespace Moonlight.Api.Http.Controllers.Admin; [ApiController] [Route("api/admin/setup")] public class SetupController : Controller { private readonly SettingsService SettingsService; private readonly DatabaseRepository UsersRepository; private readonly DatabaseRepository RolesRepository; private const string StateSettingsKey = "Moonlight.Api.Setup.State"; public SetupController( SettingsService settingsService, DatabaseRepository usersRepository, DatabaseRepository rolesRepository ) { SettingsService = settingsService; UsersRepository = usersRepository; RolesRepository = rolesRepository; } [HttpGet] [AllowAnonymous] public async Task GetSetupAsync() { var hasBeenSetup = await SettingsService.GetValueAsync(StateSettingsKey); if (hasBeenSetup) return Problem("This instance is already configured", statusCode: 405); return NoContent(); } [HttpPost] [AllowAnonymous] public async Task ApplySetupAsync([FromBody] ApplySetupDto dto) { var adminRole = await RolesRepository .Query() .FirstOrDefaultAsync(x => x.Name == "Administrators"); if (adminRole == null) { adminRole = await RolesRepository.AddAsync(new Role() { Name = "Administrators", Description = "Automatically generated group for full administrator permissions", Permissions = [ Permissions.ApiKeys.View, Permissions.ApiKeys.Create, Permissions.ApiKeys.Edit, Permissions.ApiKeys.Delete, Permissions.Roles.View, Permissions.Roles.Create, Permissions.Roles.Edit, Permissions.Roles.Delete, Permissions.Roles.Members, Permissions.Users.View, Permissions.Users.Create, Permissions.Users.Edit, Permissions.Users.Delete, Permissions.Users.Logout, Permissions.Themes.View, Permissions.Themes.Create, Permissions.Themes.Edit, Permissions.Themes.Delete, Permissions.System.Info, Permissions.System.Diagnose, ] }); } var user = await UsersRepository .Query() .FirstOrDefaultAsync(u => u.Email == dto.AdminEmail); if (user == null) { await UsersRepository.AddAsync(new User() { Email = dto.AdminEmail, Username = dto.AdminUsername, RoleMemberships = [ new RoleMember() { Role = adminRole, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow } ], CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }); } else { user.RoleMemberships.Add(new RoleMember() { Role = adminRole, CreatedAt = DateTimeOffset.UtcNow, UpdatedAt = DateTimeOffset.UtcNow }); await UsersRepository.UpdateAsync(user); } await SettingsService.SetValueAsync(StateSettingsKey, true); return NoContent(); } }