diff --git a/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a34cad3f2a12a8128da4362cc316a077d7b189b1
--- /dev/null
+++ b/Tsi1.Api/Tsi1.Api/Controllers/ForumController.cs
@@ -0,0 +1,84 @@
+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 ForumController : ControllerBase
+    {
+        private readonly IForumService _forumService;
+
+        public ForumController(IForumService forumService)
+        {
+            _forumService = forumService;
+        }
+
+        [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)]
+        [HttpGet("GetForums/{courseId}")]
+        public async Task<IActionResult> GetForums(int courseId)
+        {
+            var result = await _forumService.GetForums(courseId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok(result.Data);
+        }
+
+        [Authorize(UserTypes.Professor)]
+        [HttpPost("Create")]
+        public async Task<IActionResult> Create(ForumCreateDto newForum)
+        {
+            var result = await _forumService.Create(newForum);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok();
+        }
+
+        [Authorize(UserTypes.Professor)]
+        [HttpDelete("Delete/{forumId}")]
+        public async Task<IActionResult> Delete(int forumId)
+        {
+            var result = await _forumService.Delete(forumId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok();
+        }
+
+        [Authorize(Roles = UserTypes.Student)]
+        [HttpGet("Subscribe/{forumId}")]
+        public async Task<IActionResult> Subscribe(int forumId)
+        {
+            var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value);
+
+            var result = await _forumService.Subscribe(forumId, userId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok();
+        }
+
+    }
+}
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/Controllers/PostController.cs b/Tsi1.Api/Tsi1.Api/Controllers/PostController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7c64c6c2d027f352c60633d935e7911475b4b593
--- /dev/null
+++ b/Tsi1.Api/Tsi1.Api/Controllers/PostController.cs
@@ -0,0 +1,83 @@
+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 PostController : ControllerBase
+    {
+        private readonly IPostService _postService;
+
+        private readonly IForumService _forumService;
+
+        private readonly IEmailService _emailService;
+
+        public PostController(IPostService postService, IForumService forumService,
+            IEmailService emailService)
+        {
+            _postService = postService;
+            _forumService = forumService;
+            _emailService = emailService;
+        }
+
+
+        [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)]
+        [HttpGet("GetPosts/{forumId}")]
+        public async Task<IActionResult> GetPosts(int forumId)
+        {
+            var result = await _postService.GetPosts(forumId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok(result.Data);
+        }
+
+        [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)]
+        [HttpPost("Create")]
+        public async Task<IActionResult> Create(PostCreateDto newPost)
+        {
+            var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value);
+
+            newPost.UserId = userId;
+
+            var result = await _postService.Create(newPost);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            var userEmails = await _forumService.GetSubscribedUsers(newPost.ForumId);
+
+            await _emailService.NotifyNewPostOrMessage(newPost, userEmails.Data);
+
+            return Ok();
+        }
+
+        [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)]
+        [HttpDelete("Delete/{postId}")]
+        public async Task<IActionResult> Delete(int postId)
+        {
+            var result = await _postService.Delete(postId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok();
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.Api/Controllers/PostMessageController.cs b/Tsi1.Api/Tsi1.Api/Controllers/PostMessageController.cs
new file mode 100644
index 0000000000000000000000000000000000000000..cf2cbb93fc1d54a5af16c361bd62d3d9f17425b2
--- /dev/null
+++ b/Tsi1.Api/Tsi1.Api/Controllers/PostMessageController.cs
@@ -0,0 +1,71 @@
+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 PostMessageController : ControllerBase
+    {
+        private readonly IPostMessageService _postMessageService;
+
+        public PostMessageController(IPostMessageService postMessageService)
+        {
+            _postMessageService = postMessageService;
+        }
+
+        [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)]
+        [HttpGet("GetPostMessages/{postId}")]
+        public async Task<IActionResult> GetPostMessagesPosts(int postId)
+        {
+            var result = await _postMessageService.GetPostMessages(postId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok(result.Data);
+        }
+
+        [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)]
+        [HttpPost("Create")]
+        public async Task<IActionResult> Create(PostMessageCreateDto newPostMessage)
+        {
+            var userId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "Id").Value);
+
+            newPostMessage.UserId = userId;
+
+            var result = await _postMessageService.Create(newPostMessage);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok();
+        }
+
+        [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)]
+        [HttpDelete("Delete/{postMessageId}")]
+        public async Task<IActionResult> Delete(int postMessageId)
+        {
+            var result = await _postMessageService.Delete(postMessageId);
+
+            if (result.HasError)
+            {
+                return BadRequest(result.Message);
+            }
+
+            return Ok();
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.Api/Controllers/UserController.cs b/Tsi1.Api/Tsi1.Api/Controllers/UserController.cs
index fb50bcde10ce784bd151b42eba21551aa2df2507..21b277adb29c2e7e5a64bec7d1dd1c4d56c349ed 100644
--- a/Tsi1.Api/Tsi1.Api/Controllers/UserController.cs
+++ b/Tsi1.Api/Tsi1.Api/Controllers/UserController.cs
@@ -80,5 +80,20 @@ namespace Tsi1.Api.Controllers
 
             return Ok();
         }
+
+
+        [Authorize(Roles = UserTypes.Student + ", " + UserTypes.Professor)]
+        [HttpGet("GetAll")]
+        public async Task<IActionResult> GetAll()
+        {
+            var result = await _userService.GetAll();
+
+            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 91a2dfc433e0a3a64ae8da7e6f91ad569bd78567..b1538d389b232a2eb9250b77de2ca225ad110543 100644
--- a/Tsi1.Api/Tsi1.Api/Startup.cs
+++ b/Tsi1.Api/Tsi1.Api/Startup.cs
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using AutoMapper;
 using Microsoft.AspNetCore.Authentication.JwtBearer;
 using Microsoft.AspNetCore.Builder;
 using Microsoft.AspNetCore.Hosting;
@@ -13,12 +14,15 @@ 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;
+using Tsi1.BusinessLayer.Helpers;
 using Tsi1.BusinessLayer.Interfaces;
 using Tsi1.BusinessLayer.Services;
 using Tsi1.DataLayer;
+using Tsi1.DataLayer.MongoDbConfiguration;
 
 namespace Tsi1.Api
 {
@@ -37,9 +41,24 @@ 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>();
+            services.AddScoped<IForumService, ForumService>();
+            services.AddScoped<IPostService, PostService>();
+            services.AddScoped<IPostMessageService, PostMessageService>();          
+
+            services.Configure<MailSettings>(Configuration.GetSection("MailSettings"));
+            services.AddScoped<IEmailService, EmailService>();
 
             services.AddCors();
 
@@ -94,6 +113,14 @@ namespace Tsi1.Api
                     {securityScheme, new string[] { }}
                 });
             });
+
+            // Auto Mapper Configurations  
+            var mappingConfig = new MapperConfiguration(mc => {
+                mc.AddProfile(new MappingProfile());
+            });
+
+            IMapper mapper = mappingConfig.CreateMapper();
+            services.AddSingleton(mapper);
         }
 
         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
diff --git a/Tsi1.Api/Tsi1.Api/appsettings.json b/Tsi1.Api/Tsi1.Api/appsettings.json
index e957e7ef0ebdae633178642d900f87a2f773aee3..e637ca6e8eb7e6a16d907ad18a2eb348b0fe590c 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",
@@ -9,6 +14,13 @@
     "accessTokenExpiration": 20,
     "refreshTokenExpiration": 60
   },
+  "MailSettings": {
+    "Mail": "tsi1.grupo2.2020@gmail.com",
+    "DisplayName": "tsi1 grupo 2 2020",
+    "Password": "VamoTSI.2020",
+    "Host": "smtp.gmail.com",
+    "Port": 587
+  },
   "Logging": {
     "LogLevel": {
       "Default": "Information",
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2756562ff74849602f0f89d682c40384ea6d219f
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumCreateDto.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class ForumCreateDto
+    {
+        public string Name { get; set; }
+
+        public int CourseId { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumPreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumPreviewDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..efe56b67319500b2cc0014de56d445304fe488fc
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/ForumPreviewDto.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class ForumPreviewDto
+    {
+        public int Id { get; set; }
+
+        public string Name { get; set; }
+    }
+}
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/Dtos/PostCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostCreateDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..91eae2bf160faca45e869a0f03fb101e337fe85f
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostCreateDto.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json.Serialization;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class PostCreateDto
+    {
+        public string Title { get; set; }
+
+        public int ForumId { get; set; }
+
+        [JsonIgnore]
+        public int UserId { get; set; }
+
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessageCreateDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessageCreateDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..84900b4981cce5bfc66b8608f8b69898b539636a
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessageCreateDto.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json.Serialization;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class PostMessageCreateDto
+    {
+        public string Content { get; set; }
+
+        [JsonIgnore]
+        public int UserId { get; set; }
+
+        public int PostId { get; set; }
+
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessagePreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessagePreviewDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..cad57d7938a6e616a89e7d82e5a9d85909364296
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostMessagePreviewDto.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class PostMessagePreviewDto
+    {
+        public int Id { get; set; }
+
+        public string Content { get; set; }
+
+        public DateTime Date { get; set; }
+
+        public int UserId { get; set; }
+
+        public int PostId { get; set; }
+
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostPreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostPreviewDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..526ca193b0a22f3474086050ffa6c428a4035f46
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/PostPreviewDto.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class PostPreviewDto
+    {
+        public int Id { get; set; }
+
+        public string Title { get; set; }
+
+        public DateTime Date { get; set; }
+
+        public int ForumId { get; set; }
+
+        public int UserId { get; set; }
+
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Dtos/UserPreviewDto.cs b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/UserPreviewDto.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bb62ecbee0d56efccbdf725ed267b51d08c31dd3
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Dtos/UserPreviewDto.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.BusinessLayer.Dtos
+{
+    public class UserPreviewDto
+    {
+        public int Id { get; set; }
+
+        public string Username { get; set; }
+
+        public string FirstName { get; set; }
+
+        public string LastName { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs
index e36e8f1980228f519813ae1e19ef6452e8a0a365..0dbeef495bbeaf299bc1edeeeac6b1b653eaa583 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/ErrorMessages.cs
@@ -9,5 +9,13 @@ namespace Tsi1.BusinessLayer.Helpers
         public const string UserDoesNotExist = "El usuario '{0}' no existe";
         public const string IncorrectPassword = "Contraseña incorrecta";
         public const string UserTypeDoesNotExist = "El tipo de usuario con id '{0}' no existe";
+
+        public const string ForumDoesNotExist = "El foro con id '{0}' no existe";
+        public const string PostDoesNotExist = "El post con id '{0}' no existe";
+        public const string PostMessageDoesNotExist = "El mensage con id '{0}' no existe";
+
+        public const string CannotConnectToSmtpServer = "No se pudo conectar al servidor SMTP";
+        public const string CannotAuthenticateToSmtpServer = "No se pudo autenticar en el servidor SMTP";
+        public const string CannotSendEmail = "No se pudo mandar el mail con asunto {0}";
     }
 }
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MailSettings.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MailSettings.cs
new file mode 100644
index 0000000000000000000000000000000000000000..c7500384882dff2a95347fc29a607ee6c292d47c
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MailSettings.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.BusinessLayer.Helpers
+{
+    public class MailSettings
+    {
+        public string Mail { get; set; }
+
+        public string DisplayName { get; set; }
+        
+        public string Password { get; set; }
+        
+        public string Host { get; set; }
+        
+        public int Port { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs
new file mode 100644
index 0000000000000000000000000000000000000000..02ab611713d3080fc3ac99271dcd1787cde1518a
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Helpers/MappingProfile.cs
@@ -0,0 +1,38 @@
+using AutoMapper;
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.BusinessLayer.Helpers
+{
+    public class MappingProfile : Profile
+    {
+        public MappingProfile()
+        {
+            CreateMap<Forum, ForumCreateDto>();
+            CreateMap<Forum, ForumPreviewDto>();
+            CreateMap<Post, PostCreateDto>();
+            CreateMap<Post, PostPreviewDto>();
+            CreateMap<PostMessage, PostMessageCreateDto>();
+            CreateMap<PostMessage, PostMessagePreviewDto>();
+            CreateMap<Message, MessagePreviewDto>();
+            CreateMap<Message, MessageCreateDto>();
+            CreateMap<User, UserPreviewDto>();
+            CreateMap<User, UserRegisterDto>();
+
+            CreateMap<ForumCreateDto, Forum>();
+            CreateMap<ForumPreviewDto, Forum>();
+            CreateMap<PostCreateDto, Post>();
+            CreateMap<PostPreviewDto, Post>();
+            CreateMap<PostMessageCreateDto, PostMessage>();
+            CreateMap<PostMessagePreviewDto, PostMessage>();
+            CreateMap<MessagePreviewDto, Message>();
+            CreateMap<MessageCreateDto, Message>();
+            CreateMap<UserPreviewDto, User>();
+            CreateMap<UserRegisterDto, User>();
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IEmailService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IEmailService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4f68ea6c1064f22937bc6ded6f426c0f2829fab7
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IEmailService.cs
@@ -0,0 +1,18 @@
+using MimeKit;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.BusinessLayer.Interfaces
+{
+    public interface IEmailService
+    {
+        Task<ServiceResult<bool>> SendEmailAsync(MimeMessage message);
+
+        Task<ServiceResult<bool>> NotifyNewPostOrMessage(PostCreateDto postCreateDto, List<string> users);
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..12d94600ab697452919232f3f12239614f811fe2
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IForumService.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.BusinessLayer.Interfaces
+{
+    public interface IForumService
+    {
+        Task<ServiceResult<List<ForumPreviewDto>>> GetForums(int courseId);
+
+        Task<ServiceResult<Forum>> Create(ForumCreateDto newForum);
+
+        Task<ServiceResult<Forum>> Delete(int forumId);
+
+        Task<ServiceResult<List<string>>> GetSubscribedUsers(int forumId);
+
+        Task<ServiceResult<List<bool>>> Subscribe(int forumId, int userId);
+    }
+}
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/Interfaces/IPostMessageService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostMessageService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a1b34f403dc64bc82c1609eaf85f4a7656640308
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostMessageService.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.BusinessLayer.Interfaces
+{
+    public interface IPostMessageService
+    {
+        Task<ServiceResult<List<PostMessagePreviewDto>>> GetPostMessages(int postId);
+
+        Task<ServiceResult<PostMessage>> Create(PostMessageCreateDto newPostMessage);
+
+        Task<ServiceResult<PostMessage>> Delete(int postMessageId);
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..40dbc56c173fcd990aa3c43ae8c6c5d8dac8d5ea
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IPostService.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.BusinessLayer.Interfaces
+{
+    public interface IPostService
+    {
+        Task<ServiceResult<List<PostPreviewDto>>> GetPosts(int forumId);
+
+        Task<ServiceResult<Post>> Create(PostCreateDto newPost);
+
+        Task<ServiceResult<Post>> Delete(int postId);
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs
index fb5470f6ae4f7e64e5ebdee73b060926276e18a3..3e6742718302d55ca3993f3e526e8871efa5a5cd 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IUserService.cs
@@ -11,6 +11,9 @@ namespace Tsi1.BusinessLayer.Interfaces
     public interface IUserService
     {
         Task<ServiceResult<User>> Authenticate(string username, string password);
+
         Task<ServiceResult<User>> Create(UserRegisterDto dto, string type);
+
+        Task<ServiceResult<List<UserPreviewDto>>> GetAll();
     }
 }
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/EmailService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/EmailService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..fad2cf7baa0a7069eb16970db32cc6b0f8efe24e
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/EmailService.cs
@@ -0,0 +1,94 @@
+using MailKit;
+using MailKit.Net.Smtp;
+using MailKit.Security;
+using Microsoft.Extensions.Options;
+using MimeKit;
+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;
+
+namespace Tsi1.BusinessLayer.Services
+{
+    public class EmailService : IEmailService
+    {
+        private readonly MailSettings _mailSettings;
+
+        public EmailService(IOptions<MailSettings> mailSettings)
+        {
+            _mailSettings = mailSettings.Value;
+        }
+
+        public async Task<ServiceResult<bool>> SendEmailAsync(MimeMessage message)
+        {
+            ServiceResult<bool> result = new ServiceResult<bool>();
+
+            message.Sender = MailboxAddress.Parse(_mailSettings.Mail);
+
+            var client = new SmtpClient();
+            client.CheckCertificateRevocation = false;
+
+            try
+            {
+                await client.ConnectAsync(_mailSettings.Host, _mailSettings.Port, SecureSocketOptions.StartTls);
+            }
+            catch (Exception e)
+            {
+                result.HasError = true;
+                result.Message = ErrorMessages.CannotConnectToSmtpServer;
+                return result;
+            }
+
+            try
+            {
+                await client.AuthenticateAsync(_mailSettings.Mail, _mailSettings.Password);
+            }
+            catch (Exception)
+            {
+                result.HasError = true;
+                result.Message = ErrorMessages.CannotAuthenticateToSmtpServer;
+                return result;
+            }
+
+            try
+            {
+                await client.SendAsync(message);
+            }
+            catch (Exception)
+            {
+                result.HasError = true;
+                result.Message = string.Format(ErrorMessages.CannotSendEmail, message.Subject);
+                return result;
+            }
+
+            await client.DisconnectAsync(true);
+
+            return result;
+        }
+
+        public async Task<ServiceResult<bool>> NotifyNewPostOrMessage(PostCreateDto postCreateDto,  List<string> users)
+        {
+            var message = new MimeMessage();
+
+            foreach (var user in users)
+            {
+                message.To.Add(MailboxAddress.Parse(user));
+            }
+
+            message.Subject = $"Nuevo Post: {postCreateDto.Title}";
+            message.Body = new TextPart("html")
+            {
+                Text = $"<p> Hay un nuevo post perteneciente al foro suscripto."
+            };
+
+            var result = await SendEmailAsync(message);
+
+            return result;
+        }
+
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..827cd381abf5ff45ff7dc02e1ab5029ae9e127f7
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/ForumService.cs
@@ -0,0 +1,118 @@
+using AutoMapper;
+using Microsoft.EntityFrameworkCore;
+using Org.BouncyCastle.Math.EC.Rfc7748;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+using Tsi1.BusinessLayer.Interfaces;
+using Tsi1.DataLayer;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.BusinessLayer.Services
+{
+    public class ForumService : IForumService
+    {
+        private readonly Tsi1Context _context;
+
+        private readonly IMapper _mapper;
+
+        public ForumService(Tsi1Context context, IMapper mapper)
+        {
+            _context = context;
+            _mapper = mapper;
+        }
+
+        public async Task<ServiceResult<Forum>> Create(ForumCreateDto newForum)
+        {
+            var result = new ServiceResult<Forum>();
+
+            var forum = _mapper.Map<Forum>(newForum);
+
+            _context.Forums.Add(forum);
+            await _context.SaveChangesAsync();
+
+            result.Data = forum;
+
+            return result;
+        }
+
+        public async Task<ServiceResult<Forum>> Delete(int forumId)
+        {
+            var result = new ServiceResult<Forum>();
+
+            var forum = await _context.Forums.FirstOrDefaultAsync(x => x.Id == forumId);
+
+            if (forum == null)
+            {
+                result.HasError = true;
+                result.Message = string.Format(ErrorMessages.ForumDoesNotExist, forumId);
+                return result;
+            }
+
+            _context.Forums.Remove(forum);
+
+            await _context.SaveChangesAsync();
+
+            return result;
+        }
+
+        public async Task<ServiceResult<List<ForumPreviewDto>>> GetForums(int courseId)
+        {
+            var result = new ServiceResult<List<ForumPreviewDto>>();
+
+            var forums = await _context.Forums
+                .Where(x => x.CourseId == courseId)
+                .ToListAsync();
+
+            var forumDtos = _mapper.Map<List<ForumPreviewDto>>(forums);
+
+            result.Data = forumDtos;
+
+            return result;
+        }
+
+        public async Task<ServiceResult<List<string>>> GetSubscribedUsers(int forumId)
+        {
+            var result = new ServiceResult<List<string>>();
+
+            var userEmails = await _context.ForumUsers
+                .Where(x => x.ForumId == forumId)
+                .Select(x => x.User.Email)
+                .ToListAsync();
+
+            result.Data = userEmails;
+
+            return result;
+        }
+
+        public async Task<ServiceResult<List<bool>>> Subscribe(int forumId, int userId)
+        {
+            var result = new ServiceResult<List<bool>>();
+
+            var forum = await _context.Forums.FirstOrDefaultAsync(x => x.Id == forumId);
+
+            if (forum == null)
+            {
+                result.HasError = true;
+                result.Message = string.Format(ErrorMessages.ForumDoesNotExist, forumId);
+                return result;
+            }
+
+            var forumUser = new ForumUser
+            {
+                ForumId = forumId,
+                UserId = userId,
+            };
+
+            _context.ForumUsers.Add(forumUser);
+
+            await _context.SaveChangesAsync();
+
+            return result;
+        }
+    }
+}
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.BusinessLayer/Services/PostMessageService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/PostMessageService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..067a3317b0b92812470a91b85d613ef5266e440a
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/PostMessageService.cs
@@ -0,0 +1,79 @@
+using AutoMapper;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+using Tsi1.BusinessLayer.Interfaces;
+using Tsi1.DataLayer;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.BusinessLayer.Services
+{
+    public class PostMessageService : IPostMessageService
+    {
+        private readonly Tsi1Context _context;
+
+        private readonly IMapper _mapper;
+
+        public PostMessageService(Tsi1Context context, IMapper mapper)
+        {
+            _context = context;
+            _mapper = mapper;
+        }
+
+        public async Task<ServiceResult<PostMessage>> Create(PostMessageCreateDto newPostMessage)
+        {
+            var result = new ServiceResult<PostMessage>();
+
+            var postMessage = _mapper.Map<PostMessage>(newPostMessage);
+
+            postMessage.Date = DateTime.Now;
+
+            _context.PostMessages.Add(postMessage);
+            await _context.SaveChangesAsync();
+
+            result.Data = postMessage;
+
+            return result;
+        }
+
+        public async Task<ServiceResult<PostMessage>> Delete(int postMessageId)
+        {
+            var result = new ServiceResult<PostMessage>();
+
+            var postMessage = await _context.PostMessages.FirstOrDefaultAsync(x => x.Id == postMessageId);
+
+            if (postMessage == null)
+            {
+                result.HasError = true;
+                result.Message = string.Format(ErrorMessages.PostMessageDoesNotExist, postMessageId);
+                return result;
+            }
+
+            _context.PostMessages.Remove(postMessage);
+
+            await _context.SaveChangesAsync();
+
+            return result;
+        }
+
+        public async Task<ServiceResult<List<PostMessagePreviewDto>>> GetPostMessages(int postId)
+        {
+            var result = new ServiceResult<List<PostMessagePreviewDto>>();
+
+            var postMessages = await _context.PostMessages
+                .Where(x => x.PostId == postId)
+                .ToListAsync();
+
+            var postMessageDtos = _mapper.Map<List<PostMessagePreviewDto>>(postMessages);
+
+            result.Data = postMessageDtos;
+
+            return result;
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/PostService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/PostService.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0d625f4d02207dfae95d3c44aac8555516f83b40
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/PostService.cs
@@ -0,0 +1,79 @@
+using AutoMapper;
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Dtos;
+using Tsi1.BusinessLayer.Helpers;
+using Tsi1.BusinessLayer.Interfaces;
+using Tsi1.DataLayer;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.BusinessLayer.Services
+{
+    public class PostService : IPostService
+    {
+        private readonly Tsi1Context _context;
+
+        private readonly IMapper _mapper;
+
+        public PostService(Tsi1Context context, IMapper mapper)
+        {
+            _context = context;
+            _mapper = mapper;
+        }
+
+        public async Task<ServiceResult<Post>> Create(PostCreateDto newPost)
+        {
+            var result = new ServiceResult<Post>();
+
+            var post = _mapper.Map<Post>(newPost);
+
+            post.Date = DateTime.Now;
+
+            _context.Posts.Add(post);
+            await _context.SaveChangesAsync();
+
+            result.Data = post;
+
+            return result;
+        }
+
+        public async Task<ServiceResult<Post>> Delete(int postId)
+        {
+            var result = new ServiceResult<Post>();
+
+            var post = await _context.Posts.FirstOrDefaultAsync(x => x.Id == postId);
+
+            if (post == null)
+            {
+                result.HasError = true;
+                result.Message = string.Format(ErrorMessages.PostDoesNotExist, postId);
+                return result;
+            }
+
+            _context.Posts.Remove(post);
+
+            await _context.SaveChangesAsync();
+
+            return result;
+        }
+
+        public async Task<ServiceResult<List<PostPreviewDto>>> GetPosts(int forumId)
+        {
+            var result = new ServiceResult<List<PostPreviewDto>>();
+
+            var posts = await _context.Posts
+                .Where(x => x.ForumId == forumId)
+                .ToListAsync();
+
+            var postDtos = _mapper.Map<List<PostPreviewDto>>(posts);
+
+            result.Data = postDtos;
+
+            return result;
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/UserService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/UserService.cs
index b134703ea0c88827d65103896b470236209503b4..e824af21ada188ab0a3221025a1959230a1135ef 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Services/UserService.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/UserService.cs
@@ -1,6 +1,8 @@
-using Microsoft.EntityFrameworkCore;
+using AutoMapper;
+using Microsoft.EntityFrameworkCore;
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Tsi1.BusinessLayer.Dtos;
@@ -15,9 +17,12 @@ namespace Tsi1.BusinessLayer.Services
     {
         private readonly Tsi1Context _context;
 
-        public UserService(Tsi1Context context)
+        private readonly IMapper _mapper;
+
+        public UserService(Tsi1Context context, IMapper mapper)
         {
             _context = context;
+            _mapper = mapper;
         }
 
         public async Task<ServiceResult<User>> Authenticate(string username, string password)
@@ -84,5 +89,20 @@ namespace Tsi1.BusinessLayer.Services
 
             return result;
         }
+
+        public async Task<ServiceResult<List<UserPreviewDto>>> GetAll()
+        {
+            var result = new ServiceResult<List<UserPreviewDto>>();
+
+            var users = await _context.Users
+                .Where(x => x.UserType.Name != UserTypes.FacultyAdmin)
+                .ToListAsync();
+
+            var usersDto = _mapper.Map<List<UserPreviewDto>>(users);
+
+            result.Data = usersDto;
+
+            return result;
+        }
     }
 }
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj b/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj
index 71bca384a32afadf9f0d5acbb9ad681f05bc0cfa..a21bff7c2af2796490606eab2c96c0b6c51598ae 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Tsi1.BusinessLayer.csproj
@@ -4,6 +4,13 @@
     <TargetFramework>netcoreapp3.1</TargetFramework>
   </PropertyGroup>
 
+  <ItemGroup>
+    <PackageReference Include="AutoMapper" Version="10.1.1" />
+    <PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.0" />
+    <PackageReference Include="MailKit" Version="2.9.0" />
+    <PackageReference Include="MimeKit" Version="2.9.2" />
+  </ItemGroup>
+
   <ItemGroup>
     <ProjectReference Include="..\Tsi1.DataLayer\Tsi1.DataLayer.csproj" />
   </ItemGroup>
diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs
index c884a8829e830ad5a51d858d4da3300288d039cf..c2ee29e9f389e639bb6e0602e86689d371eba172 100644
--- a/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs
+++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Course.cs
@@ -10,6 +10,7 @@ namespace Tsi1.DataLayer.Entities
         {
             StudentCourses = new HashSet<StudentCourse>();
             ProfessorCourses = new HashSet<ProfessorCourse>();
+            Forums = new HashSet<Forum>();
         }
 
         public int Id { get; set; }
@@ -17,5 +18,6 @@ namespace Tsi1.DataLayer.Entities
 
         public ICollection<StudentCourse> StudentCourses { get; set; }
         public ICollection<ProfessorCourse> ProfessorCourses { get; set; }
+        public ICollection<Forum> Forums { get; set; }
     }
 }
diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs
new file mode 100644
index 0000000000000000000000000000000000000000..197e1e01af9d0576764a418b53a2e165a0834ada
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Forum.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.DataLayer.Entities
+{
+    public class Forum
+    {
+        public Forum()
+        {
+            Posts = new HashSet<Post>();
+            ForumUsers = new HashSet<ForumUser>();
+        }
+
+        public int Id { get; set; }
+
+        public string Name { get; set; }
+
+        public int CourseId { get; set; }
+
+        public Course Course { get; set; }
+
+        public ICollection<Post> Posts { get; set; }
+        public ICollection<ForumUser> ForumUsers { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/ForumUser.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/ForumUser.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1559edb73db90702240b13c7a5e7d7fc04a35bbe
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Entities/ForumUser.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.DataLayer.Entities
+{
+    public class ForumUser
+    {
+        public int ForumId { get; set; }
+        public int UserId { get; set; }
+
+        public Forum Forum { get; set; }
+        public User User { get; set; }
+    }
+}
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/Entities/Post.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/Post.cs
new file mode 100644
index 0000000000000000000000000000000000000000..af9cf84e9998163e934a6ccfbef44e804680cc99
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Entities/Post.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.DataLayer.Entities
+{
+    public class Post
+    {
+        public Post()
+        {
+            PostMessages = new HashSet<PostMessage>();
+        }
+
+        public int Id { get; set; }
+
+        public string Title { get; set; }
+
+        public DateTime Date { get; set; }
+
+        public int ForumId { get; set; }
+
+        public Forum Forum { get; set; }
+
+        public int UserId { get; set; }
+
+        public User User { get; set; }
+
+        public ICollection<PostMessage> PostMessages { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/PostMessage.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/PostMessage.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0e73c2ab6ea02ae3122df9a739f404022360cc2b
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Entities/PostMessage.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Tsi1.DataLayer.Entities
+{
+    public class PostMessage
+    {
+        public int Id { get; set; }
+
+        public string Content { get; set; }
+
+        public DateTime Date { get; set; }
+
+        public int UserId { get; set; }
+
+        public User User { get; set; }
+
+        public int PostId { get; set; }
+
+        public Post Post { get; set; }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs b/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs
index 637f94585126ec278d5f377993df55565e53e72c..dd7e8041f4af07d4d4fc0da1289bc83989cea95f 100644
--- a/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs
+++ b/Tsi1.Api/Tsi1.DataLayer/Entities/User.cs
@@ -6,6 +6,13 @@ namespace Tsi1.DataLayer.Entities
 {
     public class User
     {
+        public User()
+        {
+            Posts = new HashSet<Post>();
+            PostMessages = new HashSet<PostMessage>();
+            ForumUsers = new HashSet<ForumUser>();
+        }
+
         public int Id { get; set; }
         public int UserTypeId { get; set; }
         public int? StudentId { get; set; }
@@ -19,5 +26,9 @@ namespace Tsi1.DataLayer.Entities
         public UserType UserType { get; set; }
         public Student Student { get; set; }
         public Professor Professor { get; set; }
+
+        public ICollection<Post> Posts { get; set; }
+        public ICollection<PostMessage> PostMessages { get; set; }
+        public ICollection<ForumUser> ForumUsers { get; set; }
     }
 }
diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0007d57ee4625c7756efa828488bb9034a6fb2bc
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumConfiguration.cs
@@ -0,0 +1,30 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.DataLayer.EntityConfiguration
+{
+    class ForumConfiguration : IEntityTypeConfiguration<Forum>
+    {
+        public void Configure(EntityTypeBuilder<Forum> builder)
+        {
+            builder.HasKey(x => x.Id);
+
+            builder.HasIndex(x => new { x.CourseId, x.Name })
+                .IsUnique();
+
+            builder.Property(x => x.Name)
+                .IsRequired()
+                .HasColumnType("character varying(50)");
+
+            builder.HasOne(x => x.Course)
+                .WithMany(x => x.Forums)
+                .HasForeignKey(x => x.CourseId);
+
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumUserConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumUserConfiguration.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e1baf07c54c78b3405d6aff2088493ad54f07195
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/ForumUserConfiguration.cs
@@ -0,0 +1,25 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.DataLayer.EntityConfiguration
+{
+    public class ForumUserConfiguration : IEntityTypeConfiguration<ForumUser>
+    {
+        public void Configure(EntityTypeBuilder<ForumUser> builder)
+        {
+            builder.HasKey(x => new { x.ForumId, x.UserId });
+
+            builder.HasOne(x => x.Forum)
+                .WithMany(x => x.ForumUsers)
+                .HasForeignKey(x => x.ForumId);
+
+            builder.HasOne(x => x.User)
+                .WithMany(x => x.ForumUsers)
+                .HasForeignKey(x => x.UserId);
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostConfiguration.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6635726cf454e1d916ff57627c04e9e90927f73e
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostConfiguration.cs
@@ -0,0 +1,34 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.DataLayer.EntityConfiguration
+{
+    class PostConfiguration : IEntityTypeConfiguration<Post>
+    {
+        public void Configure(EntityTypeBuilder<Post> builder)
+        {
+            builder.HasKey(x => x.Id);
+
+            builder.HasIndex(x => new { x.ForumId, x.Title })
+                .IsUnique();
+
+            builder.Property(x => x.Title)
+                .IsRequired()
+                .HasColumnType("character varying(100)");
+
+            builder.HasOne(x => x.User)
+                .WithMany(x => x.Posts)
+                .HasForeignKey(x => x.UserId);
+
+            builder.HasOne(x => x.Forum)
+                .WithMany(x => x.Posts)
+                .HasForeignKey(x => x.ForumId);
+
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostMessageConfiguration.cs b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostMessageConfiguration.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b44d7303e33fa3675f014d87b729de2ee8a28fbf
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/EntityConfiguration/PostMessageConfiguration.cs
@@ -0,0 +1,31 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata.Builders;
+using System;
+using System.Collections.Generic;
+using System.Security.Cryptography.X509Certificates;
+using System.Text;
+using Tsi1.DataLayer.Entities;
+
+namespace Tsi1.DataLayer.EntityConfiguration
+{
+    class PostMessageConfiguration : IEntityTypeConfiguration<PostMessage>
+    {
+        public void Configure(EntityTypeBuilder<PostMessage> builder)
+        {
+            builder.HasKey(x => x.Id);
+
+            builder.Property(x => x.Content)
+                .IsRequired()
+                .HasColumnType("character varying(10485760)");
+
+            builder.HasOne(x => x.User)
+                .WithMany(x => x.PostMessages)
+                .HasForeignKey(x => x.UserId);
+
+            builder.HasOne(x => x.Post)
+                .WithMany(x => x.PostMessages)
+                .HasForeignKey(x => x.PostId);
+
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4e0b7a47b80c66d1a28a19d96e120d66c54c5a81
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.Designer.cs
@@ -0,0 +1,354 @@
+// <auto-generated />
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using Tsi1.DataLayer;
+
+namespace Tsi1.DataLayer.Migrations
+{
+    [DbContext(typeof(Tsi1Context))]
+    [Migration("20201017193719_add-forum-post-postmessage")]
+    partial class addforumpostpostmessage
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
+                .HasAnnotation("ProductVersion", "3.1.4")
+                .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name")
+                        .IsUnique();
+
+                    b.ToTable("Courses");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CourseId", "Name")
+                        .IsUnique();
+
+                    b.ToTable("Forums");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<int>("ForumId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Title")
+                        .IsRequired()
+                        .HasColumnType("character varying(100)");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.HasIndex("ForumId", "Title")
+                        .IsUnique();
+
+                    b.ToTable("Posts");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Content")
+                        .IsRequired()
+                        .HasColumnType("character varying(10485760)");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<int>("PostId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("PostId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("PostMessages");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("IdentityCard")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("IdentityCard")
+                        .IsUnique();
+
+                    b.ToTable("Professors");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b =>
+                {
+                    b.Property<int>("ProfessorId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("ProfessorId", "CourseId");
+
+                    b.HasIndex("CourseId");
+
+                    b.ToTable("ProfessorCourses");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<int>("Age")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("IdentityCard")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("IdentityCard")
+                        .IsUnique();
+
+                    b.ToTable("Students");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b =>
+                {
+                    b.Property<int>("StudentId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("StudentId", "CourseId");
+
+                    b.HasIndex("CourseId");
+
+                    b.ToTable("StudentCourses");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("FirstName")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("LastName")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<int?>("ProfessorId")
+                        .HasColumnType("integer");
+
+                    b.Property<int?>("StudentId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserTypeId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Username")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProfessorId")
+                        .IsUnique();
+
+                    b.HasIndex("StudentId")
+                        .IsUnique();
+
+                    b.HasIndex("UserTypeId");
+
+                    b.HasIndex("Username")
+                        .IsUnique();
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.UserType", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name")
+                        .IsUnique();
+
+                    b.ToTable("UserTypes");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("Forums")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum")
+                        .WithMany("Posts")
+                        .HasForeignKey("ForumId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("Posts")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Post", "Post")
+                        .WithMany("PostMessages")
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("PostMessages")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("ProfessorCourses")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor")
+                        .WithMany("ProfessorCourses")
+                        .HasForeignKey("ProfessorId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("StudentCourses")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Student", "Student")
+                        .WithMany("StudentCourses")
+                        .HasForeignKey("StudentId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor")
+                        .WithOne("User")
+                        .HasForeignKey("Tsi1.DataLayer.Entities.User", "ProfessorId");
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Student", "Student")
+                        .WithOne("User")
+                        .HasForeignKey("Tsi1.DataLayer.Entities.User", "StudentId");
+
+                    b.HasOne("Tsi1.DataLayer.Entities.UserType", "UserType")
+                        .WithMany()
+                        .HasForeignKey("UserTypeId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.cs
new file mode 100644
index 0000000000000000000000000000000000000000..768e30710c3fbfaa2d7b97cea0373c5d15a1b5bd
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201017193719_add-forum-post-postmessage.cs
@@ -0,0 +1,127 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+namespace Tsi1.DataLayer.Migrations
+{
+    public partial class addforumpostpostmessage : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.CreateTable(
+                name: "Forums",
+                columns: table => new
+                {
+                    Id = table.Column<int>(nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    Name = table.Column<string>(type: "character varying(50)", nullable: false),
+                    CourseId = table.Column<int>(nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Forums", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Forums_Courses_CourseId",
+                        column: x => x.CourseId,
+                        principalTable: "Courses",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Posts",
+                columns: table => new
+                {
+                    Id = table.Column<int>(nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    Title = table.Column<string>(type: "character varying(100)", nullable: false),
+                    Date = table.Column<DateTime>(nullable: false),
+                    ForumId = table.Column<int>(nullable: false),
+                    UserId = table.Column<int>(nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Posts", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Posts_Forums_ForumId",
+                        column: x => x.ForumId,
+                        principalTable: "Forums",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_Posts_Users_UserId",
+                        column: x => x.UserId,
+                        principalTable: "Users",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "PostMessages",
+                columns: table => new
+                {
+                    Id = table.Column<int>(nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    Content = table.Column<string>(type: "character varying(10485760)", nullable: false),
+                    Date = table.Column<DateTime>(nullable: false),
+                    UserId = table.Column<int>(nullable: false),
+                    PostId = table.Column<int>(nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_PostMessages", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_PostMessages_Posts_PostId",
+                        column: x => x.PostId,
+                        principalTable: "Posts",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_PostMessages_Users_UserId",
+                        column: x => x.UserId,
+                        principalTable: "Users",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Forums_CourseId_Name",
+                table: "Forums",
+                columns: new[] { "CourseId", "Name" },
+                unique: true);
+
+            migrationBuilder.CreateIndex(
+                name: "IX_PostMessages_PostId",
+                table: "PostMessages",
+                column: "PostId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_PostMessages_UserId",
+                table: "PostMessages",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Posts_UserId",
+                table: "Posts",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Posts_ForumId_Title",
+                table: "Posts",
+                columns: new[] { "ForumId", "Title" },
+                unique: true);
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "PostMessages");
+
+            migrationBuilder.DropTable(
+                name: "Posts");
+
+            migrationBuilder.DropTable(
+                name: "Forums");
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.Designer.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1043ddfe8720ed2cba0a63af3e2249bfae32c700
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.Designer.cs
@@ -0,0 +1,384 @@
+// <auto-generated />
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using Tsi1.DataLayer;
+
+namespace Tsi1.DataLayer.Migrations
+{
+    [DbContext(typeof(Tsi1Context))]
+    [Migration("20201020233929_add-ForumUser-relation")]
+    partial class addForumUserrelation
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn)
+                .HasAnnotation("ProductVersion", "3.1.4")
+                .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Course", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name")
+                        .IsUnique();
+
+                    b.ToTable("Courses");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CourseId", "Name")
+                        .IsUnique();
+
+                    b.ToTable("Forums");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b =>
+                {
+                    b.Property<int>("ForumId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("ForumId", "UserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("ForumUsers");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<int>("ForumId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Title")
+                        .IsRequired()
+                        .HasColumnType("character varying(100)");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.HasIndex("ForumId", "Title")
+                        .IsUnique();
+
+                    b.ToTable("Posts");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Content")
+                        .IsRequired()
+                        .HasColumnType("character varying(10485760)");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<int>("PostId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("PostId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("PostMessages");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("IdentityCard")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("IdentityCard")
+                        .IsUnique();
+
+                    b.ToTable("Professors");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b =>
+                {
+                    b.Property<int>("ProfessorId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("ProfessorId", "CourseId");
+
+                    b.HasIndex("CourseId");
+
+                    b.ToTable("ProfessorCourses");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Student", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<int>("Age")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("IdentityCard")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("IdentityCard")
+                        .IsUnique();
+
+                    b.ToTable("Students");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b =>
+                {
+                    b.Property<int>("StudentId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("StudentId", "CourseId");
+
+                    b.HasIndex("CourseId");
+
+                    b.ToTable("StudentCourses");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("FirstName")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("LastName")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<string>("Password")
+                        .IsRequired()
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<int?>("ProfessorId")
+                        .HasColumnType("integer");
+
+                    b.Property<int?>("StudentId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserTypeId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Username")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProfessorId")
+                        .IsUnique();
+
+                    b.HasIndex("StudentId")
+                        .IsUnique();
+
+                    b.HasIndex("UserTypeId");
+
+                    b.HasIndex("Username")
+                        .IsUnique();
+
+                    b.ToTable("Users");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.UserType", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("Name")
+                        .IsUnique();
+
+                    b.ToTable("UserTypes");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("Forums")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum")
+                        .WithMany("ForumUsers")
+                        .HasForeignKey("ForumId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("ForumUsers")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum")
+                        .WithMany("Posts")
+                        .HasForeignKey("ForumId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("Posts")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Post", "Post")
+                        .WithMany("PostMessages")
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("PostMessages")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("ProfessorCourses")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor")
+                        .WithMany("ProfessorCourses")
+                        .HasForeignKey("ProfessorId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.StudentCourse", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("StudentCourses")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Student", "Student")
+                        .WithMany("StudentCourses")
+                        .HasForeignKey("StudentId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.User", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Professor", "Professor")
+                        .WithOne("User")
+                        .HasForeignKey("Tsi1.DataLayer.Entities.User", "ProfessorId");
+
+                    b.HasOne("Tsi1.DataLayer.Entities.Student", "Student")
+                        .WithOne("User")
+                        .HasForeignKey("Tsi1.DataLayer.Entities.User", "StudentId");
+
+                    b.HasOne("Tsi1.DataLayer.Entities.UserType", "UserType")
+                        .WithMany()
+                        .HasForeignKey("UserTypeId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6774e6c4df9edc6f6abab4d73202c68d9f640fd9
--- /dev/null
+++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/20201020233929_add-ForumUser-relation.cs
@@ -0,0 +1,45 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Tsi1.DataLayer.Migrations
+{
+    public partial class addForumUserrelation : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.CreateTable(
+                name: "ForumUsers",
+                columns: table => new
+                {
+                    ForumId = table.Column<int>(nullable: false),
+                    UserId = table.Column<int>(nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_ForumUsers", x => new { x.ForumId, x.UserId });
+                    table.ForeignKey(
+                        name: "FK_ForumUsers_Forums_ForumId",
+                        column: x => x.ForumId,
+                        principalTable: "Forums",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_ForumUsers_Users_UserId",
+                        column: x => x.UserId,
+                        principalTable: "Users",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ForumUsers_UserId",
+                table: "ForumUsers",
+                column: "UserId");
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "ForumUsers");
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs
index ce5698a5c0c92dd12caec2c8cf6bd1e23ed34368..993f66e459effd11bb2dc0b80bf5af6f6a65213c 100644
--- a/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs
+++ b/Tsi1.Api/Tsi1.DataLayer/Migrations/Tsi1ContextModelSnapshot.cs
@@ -38,6 +38,102 @@ namespace Tsi1.DataLayer.Migrations
                     b.ToTable("Courses");
                 });
 
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<int>("CourseId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Name")
+                        .IsRequired()
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("CourseId", "Name")
+                        .IsUnique();
+
+                    b.ToTable("Forums");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b =>
+                {
+                    b.Property<int>("ForumId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("ForumId", "UserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("ForumUsers");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<int>("ForumId")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Title")
+                        .IsRequired()
+                        .HasColumnType("character varying(100)");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.HasIndex("ForumId", "Title")
+                        .IsUnique();
+
+                    b.ToTable("Posts");
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("Content")
+                        .IsRequired()
+                        .HasColumnType("character varying(10485760)");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<int>("PostId")
+                        .HasColumnType("integer");
+
+                    b.Property<int>("UserId")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("PostId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("PostMessages");
+                });
+
             modelBuilder.Entity("Tsi1.DataLayer.Entities.Professor", b =>
                 {
                     b.Property<int>("Id")
@@ -180,6 +276,60 @@ namespace Tsi1.DataLayer.Migrations
                     b.ToTable("UserTypes");
                 });
 
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Forum", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
+                        .WithMany("Forums")
+                        .HasForeignKey("CourseId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.ForumUser", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum")
+                        .WithMany("ForumUsers")
+                        .HasForeignKey("ForumId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("ForumUsers")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.Post", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Forum", "Forum")
+                        .WithMany("Posts")
+                        .HasForeignKey("ForumId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("Posts")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
+            modelBuilder.Entity("Tsi1.DataLayer.Entities.PostMessage", b =>
+                {
+                    b.HasOne("Tsi1.DataLayer.Entities.Post", "Post")
+                        .WithMany("PostMessages")
+                        .HasForeignKey("PostId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Tsi1.DataLayer.Entities.User", "User")
+                        .WithMany("PostMessages")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+                });
+
             modelBuilder.Entity("Tsi1.DataLayer.Entities.ProfessorCourse", b =>
                 {
                     b.HasOne("Tsi1.DataLayer.Entities.Course", "Course")
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 5b5d0ce158fa6a261517baa9e4efd29e61dd2275..247b1c4e8ed3fe19cdd2ba7c310525d252ceab3c 100644
--- a/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj
+++ b/Tsi1.Api/Tsi1.DataLayer/Tsi1.DataLayer.csproj
@@ -4,6 +4,13 @@
     <TargetFramework>netcoreapp3.1</TargetFramework>
   </PropertyGroup>
 
+  <ItemGroup>
+    <Compile Remove="Migrations\20201017191517_add-forum-post-postmessage.cs" />
+    <Compile Remove="Migrations\20201017191517_add-forum-post-postmessage.Designer.cs" />
+    <Compile Remove="Migrations\20201017193319_add-forum-post-postmessage.cs" />
+    <Compile Remove="Migrations\20201017193319_add-forum-post-postmessage.Designer.cs" />
+  </ItemGroup>
+
   <ItemGroup>
     <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.4">
       <PrivateAssets>all</PrivateAssets>
@@ -15,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>
 
diff --git a/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs b/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs
index 632d64b29f9a63df47bea3b98e4a4edfd79ddbf4..1ed9f61517e498afaaa6aa2344c57856b49a5324 100644
--- a/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs
+++ b/Tsi1.Api/Tsi1.DataLayer/Tsi1Context.cs
@@ -16,6 +16,11 @@ namespace Tsi1.DataLayer
         public DbSet<Professor> Professors { get; set; }
         public DbSet<ProfessorCourse> ProfessorCourses { get; set; }
         public DbSet<Course> Courses { get; set; }
+        public DbSet<Forum> Forums { get; set; }
+        public DbSet<Post> Posts { get; set; }
+        public DbSet<PostMessage> PostMessages { get; set; }
+        public DbSet<ForumUser> ForumUsers { get; set; }
+
 
         public Tsi1Context(DbContextOptions options) : base(options) { }
 
@@ -28,6 +33,10 @@ namespace Tsi1.DataLayer
             modelBuilder.ApplyConfiguration(new ProfessorConfiguration());
             modelBuilder.ApplyConfiguration(new ProfessorCourseConfiguration());
             modelBuilder.ApplyConfiguration(new CourseConfiguration());
+            modelBuilder.ApplyConfiguration(new ForumConfiguration());
+            modelBuilder.ApplyConfiguration(new PostConfiguration());
+            modelBuilder.ApplyConfiguration(new PostMessageConfiguration());
+            modelBuilder.ApplyConfiguration(new ForumUserConfiguration());
         }
     }
 }