Add project files.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user