177 lines
7.2 KiB
C#
177 lines
7.2 KiB
C#
using CalendarReminder.Api.Data;
|
|
using CalendarReminder.Api.Services;
|
|
using CalendarReminder.Domain.Entities;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace CalendarReminder.Api.Controllers;
|
|
|
|
[Authorize]
|
|
[ApiController]
|
|
[Route("api/admin")]
|
|
public class AdminController : ControllerBase
|
|
{
|
|
private readonly AppDbContext _db;
|
|
private readonly EmailService _email;
|
|
|
|
public AdminController(AppDbContext db, EmailService email)
|
|
{
|
|
_db = db;
|
|
_email = email;
|
|
}
|
|
|
|
private bool IsAdmin => User.FindFirst("isAdmin")?.Value == "true";
|
|
|
|
// ══════════════════════════════
|
|
// RODINY
|
|
// ══════════════════════════════
|
|
|
|
[HttpGet("families")]
|
|
public async Task<IActionResult> GetFamilies()
|
|
{
|
|
if (!IsAdmin) return Forbid();
|
|
var families = await _db.Families
|
|
.Include(f => f.Users)
|
|
.Select(f => new { f.Id, f.Name, MemberCount = f.Users.Count })
|
|
.ToListAsync();
|
|
return Ok(families);
|
|
}
|
|
|
|
[HttpPost("families")]
|
|
public async Task<IActionResult> CreateFamily([FromBody] FamilyRequest req)
|
|
{
|
|
if (!IsAdmin) return Forbid();
|
|
if (await _db.Families.AnyAsync(f => f.Name == req.Name))
|
|
return BadRequest("Rodina s týmto názvom už existuje.");
|
|
var family = new Family { Name = req.Name };
|
|
_db.Families.Add(family);
|
|
await _db.SaveChangesAsync();
|
|
return Ok(new { family.Id, family.Name, MemberCount = 0 });
|
|
}
|
|
|
|
[HttpPut("families/{id}")]
|
|
public async Task<IActionResult> UpdateFamily(int id, [FromBody] FamilyRequest req)
|
|
{
|
|
if (!IsAdmin) return Forbid();
|
|
var family = await _db.Families.FindAsync(id);
|
|
if (family is null) return NotFound();
|
|
if (await _db.Families.AnyAsync(f => f.Name == req.Name && f.Id != id))
|
|
return BadRequest("Názov je obsadený.");
|
|
family.Name = req.Name;
|
|
await _db.SaveChangesAsync();
|
|
return Ok(family);
|
|
}
|
|
|
|
[HttpDelete("families/{id}")]
|
|
public async Task<IActionResult> DeleteFamily(int id)
|
|
{
|
|
if (!IsAdmin) return Forbid();
|
|
var family = await _db.Families.Include(f => f.Users).FirstOrDefaultAsync(f => f.Id == id);
|
|
if (family is null) return NotFound();
|
|
if (family.Users.Any()) return BadRequest("Rodina má členov. Najprv presun alebo odstraň používateľov.");
|
|
_db.Families.Remove(family);
|
|
await _db.SaveChangesAsync();
|
|
return NoContent();
|
|
}
|
|
|
|
// ══════════════════════════════
|
|
// POUŽÍVATELIA
|
|
// ══════════════════════════════
|
|
|
|
[HttpGet("users")]
|
|
public async Task<IActionResult> GetUsers()
|
|
{
|
|
if (!IsAdmin) return Forbid();
|
|
var users = await _db.Users
|
|
.Include(u => u.Family)
|
|
.Select(u => new {
|
|
u.Id, u.Username, u.Email, u.IsAdmin,
|
|
u.MustChangePassword, u.CreatedAt,
|
|
FamilyId = u.FamilyId,
|
|
FamilyName = u.Family != null ? u.Family.Name : null
|
|
})
|
|
.ToListAsync();
|
|
return Ok(users);
|
|
}
|
|
|
|
[HttpPost("users")]
|
|
public async Task<IActionResult> CreateUser([FromBody] CreateUserRequest req)
|
|
{
|
|
if (!IsAdmin) return Forbid();
|
|
if (await _db.Users.AnyAsync(u => u.Email == req.Email))
|
|
return BadRequest("Email je už registrovaný.");
|
|
if (await _db.Users.AnyAsync(u => u.Username == req.Username))
|
|
return BadRequest("Meno je obsadené.");
|
|
|
|
var user = new User
|
|
{
|
|
Username = req.Username,
|
|
Email = req.Email,
|
|
FamilyId = req.FamilyId,
|
|
PasswordHash = BCrypt.Net.BCrypt.HashPassword("user"),
|
|
MustChangePassword = true
|
|
};
|
|
_db.Users.Add(user);
|
|
await _db.SaveChangesAsync();
|
|
|
|
// Email notifikácia
|
|
await _email.SendAsync(req.Email, req.Username,
|
|
"👋 Vítaj v Calendar Reminder — bol ti vytvorený účet",
|
|
$"""
|
|
<div style="font-family:Segoe UI,sans-serif;max-width:520px;margin:auto;background:#161b22;color:#e1e4e8;border-radius:10px;overflow:hidden">
|
|
<div style="background:#238636;padding:1.2rem 1.5rem">
|
|
<h2 style="margin:0;color:#fff;font-size:1.1rem">👋 Bol ti vytvorený účet</h2>
|
|
</div>
|
|
<div style="padding:1.5rem">
|
|
<p style="margin:0 0 1rem">Ahoj <strong>{req.Username}</strong>, bol ti vytvorený účet v aplikácii <strong>Calendar Reminder</strong>.</p>
|
|
<table style="width:100%;border-collapse:collapse">
|
|
<tr><td style="padding:0.4rem 0;color:#8b949e;width:80px">Meno</td><td style="padding:0.4rem 0;font-weight:600">{req.Username}</td></tr>
|
|
<tr><td style="padding:0.4rem 0;color:#8b949e">Email</td><td style="padding:0.4rem 0;font-weight:600">{req.Email}</td></tr>
|
|
<tr><td style="padding:0.4rem 0;color:#8b949e">Heslo</td><td style="padding:0.4rem 0;font-weight:600">user</td></tr>
|
|
</table>
|
|
<p style="margin:1.25rem 0 0;color:#8b949e;font-size:0.88rem">Po prvom prihlásení ťa aplikácia vyzve na zmenu hesla.</p>
|
|
</div>
|
|
<div style="padding:0.75rem 1.5rem;border-top:1px solid #30363d;font-size:0.78rem;color:#6e7681">Calendar Reminder</div>
|
|
</div>
|
|
""");
|
|
|
|
return Ok(new { user.Id, user.Username, user.Email, user.FamilyId, user.MustChangePassword });
|
|
}
|
|
|
|
[HttpPut("users/{id}")]
|
|
public async Task<IActionResult> UpdateUser(int id, [FromBody] UpdateUserRequest req)
|
|
{
|
|
if (!IsAdmin) return Forbid();
|
|
var user = await _db.Users.FindAsync(id);
|
|
if (user is null) return NotFound();
|
|
if (await _db.Users.AnyAsync(u => u.Email == req.Email && u.Id != id))
|
|
return BadRequest("Email je obsadený.");
|
|
if (await _db.Users.AnyAsync(u => u.Username == req.Username && u.Id != id))
|
|
return BadRequest("Meno je obsadené.");
|
|
|
|
user.Username = req.Username;
|
|
user.Email = req.Email;
|
|
user.FamilyId = req.FamilyId;
|
|
await _db.SaveChangesAsync();
|
|
return Ok(new { user.Id, user.Username, user.Email, user.FamilyId });
|
|
}
|
|
|
|
[HttpDelete("users/{id}")]
|
|
public async Task<IActionResult> DeleteUser(int id)
|
|
{
|
|
if (!IsAdmin) return Forbid();
|
|
var myId = int.Parse(User.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier)!.Value);
|
|
if (id == myId) return BadRequest("Nemôžeš zmazať sám seba.");
|
|
var user = await _db.Users.FindAsync(id);
|
|
if (user is null) return NotFound();
|
|
_db.Users.Remove(user);
|
|
await _db.SaveChangesAsync();
|
|
return NoContent();
|
|
}
|
|
}
|
|
|
|
public record FamilyRequest(string Name);
|
|
public record CreateUserRequest(string Username, string Email, int? FamilyId);
|
|
public record UpdateUserRequest(string Username, string Email, int? FamilyId);
|