diff --git a/Tsi1.Api/Tsi1.Api/Controllers/MessageController.cs b/Tsi1.Api/Tsi1.Api/Controllers/MessageController.cs new file mode 100644 index 0000000000000000000000000000000000000000..b6b03bff80a30dcc58a3874575190b331a4233df --- /dev/null +++ b/Tsi1.Api/Tsi1.Api/Controllers/MessageController.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; + +namespace Tsi1.Api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class MessageController : ControllerBase + { + private readonly IMessageService _messageService; + + public MessageController(IMessageService messageService) + { + _messageService = messageService; + } + + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpGet("GetMessages/{receiverId}")] + public async Task<ActionResult> GetMessages(int receiverId) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + var result = await _messageService.GetMessages(userId, receiverId); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)] + [HttpPost("Send")] + public async Task<ActionResult> Send(MessageCreateDto newMessage) + { + var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value); + + newMessage.SenderId = userId; + + var result = await _messageService.Send(newMessage); + + if (result.HasError) + { + return BadRequest(result.Message); + } + + return Ok(result.Data); + } + + } +} diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs index 0c5c2155f2cabb390a140c0d999df314e08957b1..c6a4f5f77e219c2b0ef5d769949efae4528551d4 100644 --- a/Tsi1.Api/Tsi1.Api/Startup.cs +++ b/Tsi1.Api/Tsi1.Api/Startup.cs @@ -14,6 +14,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using Tsi1.Api.Infrastructure; @@ -21,6 +22,7 @@ using Tsi1.BusinessLayer.Helpers; using Tsi1.BusinessLayer.Interfaces; using Tsi1.BusinessLayer.Services; using Tsi1.DataLayer; +using Tsi1.DataLayer.MongoDbConfiguration; namespace Tsi1.Api { @@ -39,6 +41,15 @@ namespace Tsi1.Api services.AddControllers(); services.AddDbContext<Tsi1Context>(x => x.UseNpgsql(Configuration.GetConnectionString("PostgreSql"))); + + services.Configure<Tsi1DatabaseSettings>( + Configuration.GetSection(nameof(Tsi1DatabaseSettings))); + + services.AddSingleton<ITsi1DatabaseSettings>(sp => + sp.GetRequiredService<IOptions<Tsi1DatabaseSettings>>().Value); + + services.AddSingleton<IMessageService, MessageService>(); + services.AddScoped<IUserService, UserService>(); services.AddScoped<IUserTypeService, UserTypeService>(); services.AddScoped<ICourseService, CourseService>(); diff --git a/Tsi1.Api/Tsi1.Api/appsettings.json b/Tsi1.Api/Tsi1.Api/appsettings.json index e957e7ef0ebdae633178642d900f87a2f773aee3..8de3212efd973a8247f91a2ae359f60135d9b95d 100644 --- a/Tsi1.Api/Tsi1.Api/appsettings.json +++ b/Tsi1.Api/Tsi1.Api/appsettings.json @@ -2,6 +2,11 @@ "ConnectionStrings": { "PostgreSql": "Host=localhost;Database=tsi1;Username=postgres;Password=111111" }, + "Tsi1DatabaseSettings": { + "Tsi1CollectionName": "Messages", + "ConnectionString": "mongodb://localhost:27017", + "DatabaseName": "Tsi1Db" + }, "jwtTokenConfig": { "secret": "1234567890123456789", "issuer": "https://localhost:44363", diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/MessageCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/MessageCreateDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..628b095fe51b156d84d73089fd18c79f9a1b9ff9 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/MessageCreateDto.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.Json.Serialization; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class MessageCreateDto + { + [JsonIgnore] + public int SenderId { get; set; } + + public int ReceiverId { get; set; } + + public string Content { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/MessagePreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/MessagePreviewDto.cs new file mode 100644 index 0000000000000000000000000000000000000000..e49acbb8188fd93d9a6d4479a01a12e2569ebf3b --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/MessagePreviewDto.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.BusinessLayer.Dtos +{ + public class MessagePreviewDto + { + public string Id { get; set; } + + public int SenderId { get; set; } + + public int ReceiverId { get; set; } + + public string Content { get; set; } + + public string Date { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs index 95ed2d6e8f2f1d2e382d4b27728a71c05f72d58a..4563e7b0d11066b335c2adbb35f37de4732d47e8 100644 --- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs +++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs @@ -18,6 +18,8 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<Post, PostPreviewDto>(); CreateMap<PostMessage, PostMessageCreateDto>(); CreateMap<PostMessage, PostMessagePreviewDto>(); + CreateMap<Message, MessagePreviewDto>(); + CreateMap<Message, MessageCreateDto>(); CreateMap<ForumCreateDto, Forum>(); CreateMap<ForumPreviewDto, Forum>(); @@ -25,6 +27,8 @@ namespace Tsi1.BusinessLayer.Helpers CreateMap<PostPreviewDto, Post>(); CreateMap<PostMessageCreateDto, PostMessage>(); CreateMap<PostMessagePreviewDto, PostMessage>(); + CreateMap<MessagePreviewDto, Message>(); + CreateMap<MessageCreateDto, Message>(); } } } diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IMessageService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IMessageService.cs new file mode 100644 index 0000000000000000000000000000000000000000..785b46134f790b90ade833746481cb16b914c3f5 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IMessageService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; + +namespace Tsi1.BusinessLayer.Interfaces +{ + public interface IMessageService + { + Task<ServiceResult<List<MessagePreviewDto>>> GetMessages(int userId, int otherUserId); + + Task<ServiceResult<MessagePreviewDto>> Send(MessageCreateDto newMessage); + + } +} diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/MessageService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/MessageService.cs new file mode 100644 index 0000000000000000000000000000000000000000..eab3cb3f4a2440d25007d09237e542219de54096 --- /dev/null +++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/MessageService.cs @@ -0,0 +1,66 @@ +using AutoMapper; +using MongoDB.Bson; +using MongoDB.Driver; +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Tsi1.BusinessLayer.Dtos; +using Tsi1.BusinessLayer.Helpers; +using Tsi1.BusinessLayer.Interfaces; +using Tsi1.DataLayer.Entities; +using Tsi1.DataLayer.MongoDbConfiguration; + +namespace Tsi1.BusinessLayer.Services +{ + public class MessageService : IMessageService + { + private readonly IMapper _mapper; + + private readonly IMongoCollection<Message> _messages; + + public MessageService(ITsi1DatabaseSettings settings, IMapper mapper) + { + var client = new MongoClient(settings.ConnectionString); + var database = client.GetDatabase(settings.DatabaseName); + + _messages = database.GetCollection<Message>(settings.Tsi1CollectionName); + _mapper = mapper; + } + + public async Task<ServiceResult<List<MessagePreviewDto>>> GetMessages(int userId, int otherUserId) + { + var result = new ServiceResult<List<MessagePreviewDto>>(); + + var sort = Builders<Message>.Sort.Ascending("Date"); + + var messages = await _messages.Find(m => (m.SenderId == userId && m.ReceiverId == otherUserId) + || (m.SenderId == otherUserId && m.ReceiverId == userId)) + .Sort(sort) + .ToListAsync(); + + var messagesDto = _mapper.Map<List<MessagePreviewDto>>(messages); + + result.Data = messagesDto; + + return result; + } + + public async Task<ServiceResult<MessagePreviewDto>> Send(MessageCreateDto newMessage) + { + var result = new ServiceResult<MessagePreviewDto>(); + + var message = _mapper.Map<Message>(newMessage); + message.Date = DateTime.Now; + + + await _messages.InsertOneAsync(message); + + var messageDto = _mapper.Map<MessagePreviewDto>(message); + + result.Data = messageDto; + + return result; + } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Message.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Message.cs new file mode 100644 index 0000000000000000000000000000000000000000..4925699629ad1863a4860433900dd189ea8d5fc7 --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Message.cs @@ -0,0 +1,24 @@ +using MongoDB.Bson; +using MongoDB.Bson.Serialization.Attributes; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.DataLayer.Entities +{ + public class Message + { + [BsonId] + [BsonRepresentation(BsonType.ObjectId)] + public string Id { get; set; } + + public int SenderId { get; set; } + + public int ReceiverId { get; set; } + + public string Content { get; set; } + + public DateTime Date { get; set; } + + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/MongoDbConfiguration/Tsi1DatabaseSettings.cs b/Tsi1.Api/Tsi1.DataLayer/MongoDbConfiguration/Tsi1DatabaseSettings.cs new file mode 100644 index 0000000000000000000000000000000000000000..67e12a5f70efc07bad5a1f7106305d335f20c45e --- /dev/null +++ b/Tsi1.Api/Tsi1.DataLayer/MongoDbConfiguration/Tsi1DatabaseSettings.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Tsi1.DataLayer.MongoDbConfiguration +{ + public class Tsi1DatabaseSettings : ITsi1DatabaseSettings + { + public string Tsi1CollectionName { get; set; } + public string ConnectionString { get; set; } + public string DatabaseName { get; set; } + } + + public interface ITsi1DatabaseSettings + { + public string Tsi1CollectionName { get; set; } + public string ConnectionString { get; set; } + public string DatabaseName { get; set; } + } +} diff --git a/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj b/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj index c339529345145ef37fcd12c8db20f2b5385c6bfd..247b1c4e8ed3fe19cdd2ba7c310525d252ceab3c 100644 --- a/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj +++ b/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj @@ -22,6 +22,7 @@ </PackageReference> <PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.9" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.9" /> + <PackageReference Include="MongoDB.Driver" Version="2.11.3" /> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" /> </ItemGroup>