Add project files.

This commit is contained in:
roman
2026-06-05 21:39:38 +02:00
parent 63bb199a1f
commit 841037013a
28 changed files with 2342 additions and 0 deletions
@@ -0,0 +1,51 @@
using MailKit.Net.Smtp;
using MimeKit;
namespace CalendarReminder.Api.Services;
public class EmailSettings
{
public string Host { get; set; } = "";
public int Port { get; set; } = 587;
public string Username { get; set; } = "";
public string Password { get; set; } = "";
public string From { get; set; } = "";
public bool UseSsl { get; set; } = false;
}
public class EmailService
{
private readonly EmailSettings _settings;
private readonly ILogger<EmailService> _logger;
public EmailService(IConfiguration config, ILogger<EmailService> logger)
{
_settings = config.GetSection("Email").Get<EmailSettings>() ?? new EmailSettings();
_logger = logger;
}
public async Task SendAsync(string toEmail, string toName, string subject, string body)
{
try
{
var message = new MimeMessage();
message.From.Add(new MailboxAddress("CalendarReminder", _settings.From));
message.To.Add(new MailboxAddress(toName, toEmail));
message.Subject = subject;
message.Body = new TextPart("html") { Text = body };
using var client = new SmtpClient();
await client.ConnectAsync(_settings.Host, _settings.Port, _settings.UseSsl);
if (!string.IsNullOrEmpty(_settings.Username))
await client.AuthenticateAsync(_settings.Username, _settings.Password);
await client.SendAsync(message);
await client.DisconnectAsync(true);
_logger.LogInformation("Email odoslaný na {Email}", toEmail);
}
catch (Exception ex)
{
_logger.LogError(ex, "Chyba pri odosielaní emailu na {Email}", toEmail);
}
}
}
@@ -0,0 +1,71 @@
using CalendarReminder.Api.Data;
using Microsoft.EntityFrameworkCore;
namespace CalendarReminder.Api.Services;
public class ReminderNotificationService : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger<ReminderNotificationService> _logger;
public ReminderNotificationService(IServiceScopeFactory scopeFactory,
ILogger<ReminderNotificationService> logger)
{
_scopeFactory = scopeFactory;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Notification service spustený");
while (!stoppingToken.IsCancellationRequested)
{
await CheckRemindersAsync();
await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
}
}
private async Task CheckRemindersAsync()
{
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var emailService = scope.ServiceProvider.GetRequiredService<EmailService>();
var now = DateTime.UtcNow;
var windowEnd = now.AddMinutes(15);
// Nájdi remindery, ktoré sú do 15 minút a notifikácia ešte nebola odoslaná
var upcoming = await db.Reminders
.Include(r => r.User)
.Where(r => !r.IsCompleted
&& !r.NotificationSent
&& r.ReminderDate >= now
&& r.ReminderDate <= windowEnd)
.ToListAsync();
foreach (var reminder in upcoming)
{
var minutesLeft = (int)(reminder.ReminderDate - now).TotalMinutes;
var body = $"""
<h2>⏰ Pripomienka: {reminder.Title}</h2>
<p><strong>Čas:</strong> {reminder.ReminderDate:dd.MM.yyyy HH:mm}</p>
<p><strong>O:</strong> {minutesLeft} minút</p>
{(reminder.Description != null ? $"<p><strong>Popis:</strong> {reminder.Description}</p>" : "")}
<hr>
<small>CalendarReminder</small>
""";
await emailService.SendAsync(
reminder.User!.Email,
reminder.User.Username,
$"⏰ Pripomienka: {reminder.Title}",
body);
reminder.NotificationSent = true;
}
if (upcoming.Count > 0)
await db.SaveChangesAsync();
}
}
@@ -0,0 +1,39 @@
using CalendarReminder.Domain.Entities;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace CalendarReminder.Api.Services;
public class TokenService
{
private readonly IConfiguration _config;
public TokenService(IConfiguration config)
{
_config = config;
}
public string GenerateToken(User user)
{
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Secret"]!));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.Username),
new Claim(ClaimTypes.Email, user.Email)
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Audience"],
claims: claims,
expires: DateTime.UtcNow.AddDays(7),
signingCredentials: creds);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}