using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using StalwartSimpleLoginMiddleware.Contexts; using StalwartSimpleLoginMiddleware.Entities; using StalwartSimpleLoginMiddleware.Models; using StalwartSimpleLoginMiddleware.Utilities; namespace StalwartSimpleLoginMiddleware.Controllers; [ApiController] [Authorize(Roles = "Admin")] [Route("api/[controller]/[action]")] public class AdminController : ControllerBase { private readonly ApiKeyContext context; public AdminController(ApiKeyContext context) { this.context = context; } [HttpGet] public async Task ListApiKeys([FromQuery] int page = 0, [FromQuery] int limit = 100) { return await context.ApiKeys .Include(apiKey => apiKey.Members) .Skip(page * limit) .Take(limit).ToArrayAsync(); } [HttpGet] public async Task GetApiKey([FromQuery] string key) { var apiKey = await context.ApiKeys .Include(apiKey => apiKey.Members) .Select(apiKey => new ApiKey { Key = apiKey.Key, OwnerEmail = apiKey.OwnerEmail, IsAdmin = apiKey.IsAdmin, Members = apiKey.Members.ToArray() }) .FirstOrDefaultAsync(apiKey => apiKey.Key == key); if (apiKey == null) throw new BadHttpRequestException("API Key is invalid."); return apiKey; } [HttpPost] public async Task UpdateApiKeyOwnerEmail([FromBody] UpdateOwnerEmailInput input) { var rows = await context.ApiKeys.Where(apiKey => apiKey.Key == input.ApiKey) .ExecuteUpdateAsync(apiKey => apiKey.SetProperty(p => p.OwnerEmail, input.OwnerEmail)); if (rows == 0) return NotFound(); return Ok(); } [HttpPost] public async Task CreateApiKey([FromBody] ApiKeyInput newApiKeyInput) { if (string.IsNullOrEmpty(ApiKeyHelper.GetEmailDomain(newApiKeyInput.OwnerEmail))) return BadRequest("Owner Email must be a valid email address."); var apiKey = new ApiKey { Key = ApiKeyHelper.GenerateKey(), OwnerEmail = newApiKeyInput.OwnerEmail, IsAdmin = newApiKeyInput.IsAdmin, Members = newApiKeyInput.Members.Select(m => new Member { Email = m.Email, IsExternal = m.IsExternal }) .ToArray() }; context.ApiKeys.Add(apiKey); await context.SaveChangesAsync(); return CreatedAtAction(nameof(GetApiKey), new { key = apiKey.Key }, apiKey); } [HttpPost] public async Task CreateApiKeyMember([FromBody] AddApiKeyMemberInput input) { var member = new Member { ApiKeyId = input.ApiKey, Email = input.Member.Email, IsExternal = input.Member.IsExternal }; context.Members.Add(member); await context.SaveChangesAsync(); return CreatedAtAction(nameof(GetApiKey), new { key = input.ApiKey }); } [HttpDelete] public async Task DeleteApiKey([FromQuery] string key) { var rows = await context.ApiKeys.Where(apiKey => apiKey.Key == key) .ExecuteDeleteAsync(); if (rows == 0) return NotFound(); return Ok(); } [HttpDelete] public async Task DeleteApiKeyMemberEmail([FromQuery] string key, [FromQuery] string email) { var rows = await context.Members.Where(member => member.ApiKeyId == key) .Where(member => member.Email == email) .ExecuteDeleteAsync(); if (rows == 0) return NotFound(); return Ok(); } }