mirror of
https://github.com/Govor-team/Govor.git
synced 2026-07-21 19:54:55 +00:00
rework messages
+ addition LocalStorageService + tests
This commit is contained in:
@@ -39,6 +39,10 @@ public class UsersRepositoryTests
|
||||
var random = new Random();
|
||||
var users = _fixture.CreateMany<User>(random.Next(2, 10)).ToList();
|
||||
|
||||
_options = new DbContextOptionsBuilder<GovorDbContext>()
|
||||
.UseInMemoryDatabase(databaseName: "DbGovor_users_getall")
|
||||
.Options;
|
||||
|
||||
await using var context = new GovorDbContext(_options);
|
||||
var userRepository = new UsersRepository(context, _userValidator);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ using Govor.API.Services.Authentication;
|
||||
using Govor.Core.Infrastructure.Extensions;
|
||||
using Govor.Core.Models;
|
||||
using Govor.Core.Repositories.Users;
|
||||
using Govor.Core.Services;
|
||||
using Govor.API.Services.Authentication.Interfaces;
|
||||
using Moq;
|
||||
|
||||
namespace Govor.API.Tests.UnitTests.Services;
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
using AutoFixture;
|
||||
using Govor.API.Services;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Moq;
|
||||
|
||||
namespace Govor.API.Tests.UnitTests.Services;
|
||||
|
||||
[TestFixture]
|
||||
public class LocalStorageServiceTests
|
||||
{
|
||||
private Fixture _fixture;
|
||||
private IStorageService _service;
|
||||
private Mock<IWebHostEnvironment> _webHostEnvironmentMock;
|
||||
private string _tempDirectory;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_fixture = new Fixture();
|
||||
_webHostEnvironmentMock = new Mock<IWebHostEnvironment>();
|
||||
|
||||
_tempDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
|
||||
Directory.CreateDirectory(_tempDirectory);
|
||||
|
||||
_webHostEnvironmentMock.Setup(w => w.ContentRootPath).Returns(_tempDirectory);
|
||||
|
||||
_service = new LocalStorageService(_webHostEnvironmentMock.Object);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
if (Directory.Exists(_tempDirectory))
|
||||
{
|
||||
Directory.Delete(_tempDirectory, true);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Given_ValidDataAndFileName_When_SaveAsync_Then_FileIsSaved()
|
||||
{
|
||||
// Arrange
|
||||
var data = _fixture.CreateMany<byte>(1000).ToArray();
|
||||
var fileName = _fixture.Create<string>() + ".txt";
|
||||
var saveDate = DateTime.UtcNow;
|
||||
|
||||
// Act
|
||||
var url = await _service.SaveAsync(data, fileName);
|
||||
|
||||
// Assert
|
||||
Assert.That(url, Is.Not.Null);
|
||||
|
||||
// _tempDirectory/uploads/yyyy/MM/url
|
||||
var datePath = saveDate.ToString("yyyy/MM");
|
||||
var expectedFilePath = Path.Combine(_tempDirectory, "uploads", url);
|
||||
Assert.That(File.Exists(expectedFilePath), Is.True, $"Файл не найден по пути: {expectedFilePath}");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Given_EmptyName_When_SaveAsync_Should_Throw_ArgumentException()
|
||||
{
|
||||
// Arrange
|
||||
var data = _fixture.CreateMany<byte>(1000).ToArray();
|
||||
|
||||
// Act & Assert
|
||||
Assert.ThrowsAsync<ArgumentException>(async () => await _service.SaveAsync(data, string.Empty));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Given_EmptyData_When_SaveAsync_Should_Throw_ArgumentException()
|
||||
{
|
||||
// Arrange
|
||||
var name = _fixture.Create<string>();
|
||||
|
||||
// Act & Assert
|
||||
Assert.ThrowsAsync<ArgumentException>(async () => await _service.SaveAsync(default, name));
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using Govor.API.Services.Authentication;
|
||||
using Govor.Core.DTOs;
|
||||
using Govor.Core.Services;
|
||||
using Govor.API.Services.Authentication.Interfaces;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Govor.API.Controllers;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Govor.Core.Services;
|
||||
using Govor.API.Services;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
|
||||
@@ -2,17 +2,15 @@ using System.Text;
|
||||
using Govor.API.Hubs;
|
||||
using Govor.API.Services;
|
||||
using Govor.API.Services.Authentication;
|
||||
using Govor.API.Services.Authentication.Interfaces;
|
||||
using Govor.Core.Infrastructure.Extensions;
|
||||
using Govor.Core.Infrastructure.Validators;
|
||||
using Govor.Core.Models;
|
||||
using Govor.Core.Repositories;
|
||||
using Govor.Core.Repositories.Users;
|
||||
using Govor.Core.Services;
|
||||
using Govor.Data;
|
||||
using Govor.Data.Repositories;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Govor.API.Services.Authentication.Interfaces;
|
||||
using Govor.Core;
|
||||
using Govor.Core.Infrastructure.Extensions;
|
||||
using Govor.Core.Models;
|
||||
using Govor.Core.Repositories;
|
||||
using Govor.Core.Repositories.Users;
|
||||
using Govor.Core.Services;
|
||||
using Govor.Data.Repositories;
|
||||
using Govor.API.Services;
|
||||
|
||||
|
||||
namespace Govor.API.Services.Authentication;
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using Govor.Core.Models;
|
||||
|
||||
namespace Govor.Core.Services;
|
||||
namespace Govor.API.Services.Authentication.Interfaces;
|
||||
|
||||
public interface IAccountService
|
||||
{
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using Govor.Core.Models;
|
||||
|
||||
namespace Govor.Core.Services;
|
||||
namespace Govor.API.Services.Authentication.Interfaces;
|
||||
|
||||
public interface IJwtService
|
||||
{
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Text;
|
||||
using Govor.API.Services.Authentication.Interfaces;
|
||||
using Govor.Core.Models;
|
||||
using Govor.Core.Services;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Govor.Core.Models;
|
||||
|
||||
namespace Govor.Core.Services;
|
||||
namespace Govor.API.Services;
|
||||
|
||||
public interface IGroupService
|
||||
{
|
||||
@@ -0,0 +1,10 @@
|
||||
using Microsoft.AspNetCore.Http; // для IFormFile
|
||||
|
||||
namespace Govor.API.Services;
|
||||
|
||||
public interface IStorageService
|
||||
{
|
||||
Task<string> SaveAsync(byte[] data, string fileName);
|
||||
Task<Stream> LoadAsync(string url);
|
||||
Task RemoveAsync(string url);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
namespace Govor.API.Services;
|
||||
|
||||
public class LocalStorageService : IStorageService
|
||||
{
|
||||
private readonly string _storagePath;
|
||||
|
||||
public LocalStorageService(IWebHostEnvironment hostingEnvironment)
|
||||
{
|
||||
_storagePath = Path.Combine(hostingEnvironment.ContentRootPath, "uploads");
|
||||
|
||||
if (!Directory.Exists(_storagePath))
|
||||
{
|
||||
Directory.CreateDirectory(_storagePath);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> SaveAsync(byte[] data, string fileName)
|
||||
{
|
||||
if(data is null || data.Length == 0)
|
||||
throw new ArgumentException("Invalid file", nameof(data));
|
||||
|
||||
if(fileName is null || fileName.Length == 0)
|
||||
throw new ArgumentException("Invalid file name", nameof(fileName));
|
||||
|
||||
var date = DateTime.UtcNow.ToString("yyyy/MM");
|
||||
|
||||
var folder = Path.Combine(_storagePath, date);
|
||||
Directory.CreateDirectory(folder);
|
||||
|
||||
var uniqueFileName = $"{Guid.NewGuid()}_{Path.GetFileName(fileName)}";
|
||||
var fullPath = Path.Combine(folder, uniqueFileName);
|
||||
|
||||
await using var stream = new FileStream(fullPath, FileMode.Create);
|
||||
stream.WriteAsync(data, 0, data.Length);
|
||||
|
||||
return Path.Combine(date, uniqueFileName);
|
||||
}
|
||||
|
||||
public async Task<Stream> LoadAsync(string url)
|
||||
{
|
||||
var filePath = Path.Combine(_storagePath, Path.GetFileName(url));
|
||||
|
||||
if (!File.Exists(filePath))
|
||||
throw new FileNotFoundException("File not found.", filePath);
|
||||
|
||||
await using var file = new FileStream(filePath, FileMode.Open, FileAccess.Read);
|
||||
return file;
|
||||
}
|
||||
|
||||
public async Task RemoveAsync(string url)
|
||||
{
|
||||
var path = Path.Combine(_storagePath, Path.GetFileName(url));
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.Delete(path);
|
||||
}
|
||||
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace Govor.Core.Models;
|
||||
|
||||
public class MediaAttachments
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid MessageId { get; set; }
|
||||
|
||||
public MediaType Type { get; set; }
|
||||
public string FilePath { get; set; } = string.Empty; // путь к файлу (локальный или URL)
|
||||
public string MimeType { get; set; } = string.Empty;
|
||||
|
||||
public string? EncryptedKey { get; set; } // если используется отдельное шифрование
|
||||
public Message Message { get; set; } = null!;
|
||||
}
|
||||
|
||||
public enum MediaType
|
||||
{
|
||||
Image,
|
||||
Video,
|
||||
Audio,
|
||||
File,
|
||||
Voice
|
||||
}
|
||||
@@ -10,6 +10,8 @@ public class Message
|
||||
public DateTime SentAt { get; set; }
|
||||
public bool IsEdited { get; set; } = false;
|
||||
public DateTime? EditedAt { get; set; }
|
||||
public List<MessageReaction> Reactions { get; set; } = new List<MessageReaction>();
|
||||
public List<MediaAttachments> MediaAttachments { get; set; } = new List<MediaAttachments>();
|
||||
}
|
||||
|
||||
public enum RecipientType
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Govor.Core.Models;
|
||||
|
||||
public class MessageReaction
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public Guid MessageId { get; set; }
|
||||
public Message Message { get; set; }
|
||||
|
||||
public Guid UserId { get; set; }
|
||||
public User User { get; set; }
|
||||
|
||||
public string ReactionCode { get; set; } // "❤️", "🔥", "👍", ":custom_emoji:"
|
||||
public DateTime ReactedAt { get; set; } = DateTime.UtcNow;
|
||||
}
|
||||
Reference in New Issue
Block a user