diff options
Diffstat (limited to 'Backend')
-rw-r--r-- | Backend/Api/Api/Controllers/MessageController.cs | 44 | ||||
-rw-r--r-- | Backend/Api/Api/Controllers/UserController.cs | 43 | ||||
-rw-r--r-- | Backend/Api/Api/Database/DatabaseConnection.cs | 1 | ||||
-rw-r--r-- | Backend/Api/Api/Interfaces/IDatabaseConnection.cs | 1 | ||||
-rw-r--r-- | Backend/Api/Api/Interfaces/IMessageService.cs | 11 | ||||
-rw-r--r-- | Backend/Api/Api/Interfaces/IPostService.cs | 1 | ||||
-rw-r--r-- | Backend/Api/Api/Interfaces/IUserService.cs | 4 | ||||
-rw-r--r-- | Backend/Api/Api/Models/Location.cs | 5 | ||||
-rw-r--r-- | Backend/Api/Api/Models/Message.cs | 27 | ||||
-rw-r--r-- | Backend/Api/Api/Models/Post.cs | 6 | ||||
-rw-r--r-- | Backend/Api/Api/Models/User.cs | 13 | ||||
-rw-r--r-- | Backend/Api/Api/Program.cs | 16 | ||||
-rw-r--r-- | Backend/Api/Api/Services/ChatHub.cs | 72 | ||||
-rw-r--r-- | Backend/Api/Api/Services/LocationService.cs | 10 | ||||
-rw-r--r-- | Backend/Api/Api/Services/MessageService.cs | 80 | ||||
-rw-r--r-- | Backend/Api/Api/Services/PostService.cs | 19 | ||||
-rw-r--r-- | Backend/Api/Api/Services/UserService.cs | 88 | ||||
-rw-r--r-- | Backend/Api/Api/appsettings.json | 3 |
18 files changed, 434 insertions, 10 deletions
diff --git a/Backend/Api/Api/Controllers/MessageController.cs b/Backend/Api/Api/Controllers/MessageController.cs new file mode 100644 index 0000000..750fc5f --- /dev/null +++ b/Backend/Api/Api/Controllers/MessageController.cs @@ -0,0 +1,44 @@ +using System.Data; +using Api.Interfaces; +using Api.Models; +using Api.Services; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace Api.Controllers +{ + [Route("api/[controller]")] + [ApiController] + public class MessageController : ControllerBase + { + + private readonly IJwtService _jwtService; + private readonly IMessageService _messageService; + public MessageController( IJwtService jwtService,IMessageService messageService) + { + + _jwtService = jwtService; + _messageService = messageService; + + } + [HttpPost("add")] + [Authorize(Roles = "User")] + public async Task<ActionResult<Message>> addMessage([FromBody] MessageReceive msg) + { + var msgTemp = await _messageService.addMessage(msg); + if(msgTemp == null) + return BadRequest(); + return Ok(msgTemp); + } + [HttpGet("myMessages")] + [Authorize(Roles = "User")] + public async Task<ActionResult<List<MessageSend>>> getMyMessages() + { + var msgTemp = await _messageService.getReceiverMessage(); + if (msgTemp == null) + return BadRequest(); + return Ok(msgTemp); + } + } +} diff --git a/Backend/Api/Api/Controllers/UserController.cs b/Backend/Api/Api/Controllers/UserController.cs index 1ef8234..7764af1 100644 --- a/Backend/Api/Api/Controllers/UserController.cs +++ b/Backend/Api/Api/Controllers/UserController.cs @@ -55,5 +55,48 @@ namespace Api.Controllers return Ok(rez); return BadRequest(); } + [HttpGet("{id}/id/profile")] + [Authorize(Roles = "User")] + public async Task<ActionResult<UserSend>> GetUserById(string id) + { + var rez = await _userService.getUserById(id); + if (rez != null) + return Ok(rez); + return BadRequest(); + } + [HttpGet("history")] + [Authorize(Roles = "User")] + public async Task<ActionResult<List<PostSend>>> ViewHistory() + { + var id = await _userService.UserIdFromJwt(); + var rez = await _postService.UserHistory(id); + if (rez != null) + return Ok(rez); + return BadRequest(); + } + + [HttpGet("{id}/followers")] + [Authorize(Roles = "User")] + public async Task<ActionResult<List<UserSend>>> GetFollowers(string id) + { + return Ok(await _userService.GetFollowers(id)); + } + + [HttpGet("{id}/following")] + [Authorize(Roles = "User")] + public async Task<ActionResult<List<UserSend>>> GetFollowing(string id) + { + return Ok(await _userService.GetFollowing(id)); + } + + [HttpGet("addFollower")] + [Authorize(Roles = "User")] + public async Task<ActionResult<List<UserSend>>> AddFollower(string userId, string followerId) + { + return Ok(await _userService.AddFollower(userId, followerId)); + } + + + } } diff --git a/Backend/Api/Api/Database/DatabaseConnection.cs b/Backend/Api/Api/Database/DatabaseConnection.cs index f26b88e..eaf047a 100644 --- a/Backend/Api/Api/Database/DatabaseConnection.cs +++ b/Backend/Api/Api/Database/DatabaseConnection.cs @@ -10,5 +10,6 @@ namespace Api.Database public string PostCollectionName { get; set; } = String.Empty; public string FileCollectionName { get; set; } = String.Empty; public string LocationCollectionName { get; set; } = String.Empty; + public string MessageCollectionname { get; set; }= String.Empty; } } diff --git a/Backend/Api/Api/Interfaces/IDatabaseConnection.cs b/Backend/Api/Api/Interfaces/IDatabaseConnection.cs index 17b5262..a8fec9a 100644 --- a/Backend/Api/Api/Interfaces/IDatabaseConnection.cs +++ b/Backend/Api/Api/Interfaces/IDatabaseConnection.cs @@ -8,5 +8,6 @@ string PostCollectionName { get; set; } string FileCollectionName { get; set; } string LocationCollectionName { get; set; } + string MessageCollectionname { get; set; } } } diff --git a/Backend/Api/Api/Interfaces/IMessageService.cs b/Backend/Api/Api/Interfaces/IMessageService.cs new file mode 100644 index 0000000..712b344 --- /dev/null +++ b/Backend/Api/Api/Interfaces/IMessageService.cs @@ -0,0 +1,11 @@ +using Api.Models; + +namespace Api.Interfaces +{ + public interface IMessageService + { + Task<Message> addMessage(MessageReceive msg); + Task<List<MessageSend>> getReceiverMessage(); + MessageSend messageToMessageSend(Message msg); + } +}
\ No newline at end of file diff --git a/Backend/Api/Api/Interfaces/IPostService.cs b/Backend/Api/Api/Interfaces/IPostService.cs index fc2ae03..12a5fe8 100644 --- a/Backend/Api/Api/Interfaces/IPostService.cs +++ b/Backend/Api/Api/Interfaces/IPostService.cs @@ -18,5 +18,6 @@ namespace Api.Interfaces Task<PostSendPage> SearchPosts(string locid, int page = 0, int sorttype = 1, int filterdate = 1); int DateEnumToDays(int filterdate); Task<List<PostSend>> GetUsersPosts(string id); + Task<List<PostSend>> UserHistory(string userid); } }
\ No newline at end of file diff --git a/Backend/Api/Api/Interfaces/IUserService.cs b/Backend/Api/Api/Interfaces/IUserService.cs index 313e909..5770de1 100644 --- a/Backend/Api/Api/Interfaces/IUserService.cs +++ b/Backend/Api/Api/Interfaces/IUserService.cs @@ -26,5 +26,9 @@ namespace Api.Interfaces Task<Boolean> AddOrChangePfp(string userid, IFormFile image); Task<UserSend> GetUserData(string username); Task<UserSend> GetSelfUserData(string id); + + Task<Boolean> AddFollower(string userId,string followerId); + Task<List<UserSend>> GetFollowers(string id); + Task<List<UserSend>> GetFollowing(string id); } } diff --git a/Backend/Api/Api/Models/Location.cs b/Backend/Api/Api/Models/Location.cs index 3402f6c..b2f0aad 100644 --- a/Backend/Api/Api/Models/Location.cs +++ b/Backend/Api/Api/Models/Location.cs @@ -22,8 +22,9 @@ namespace Api.Models public enum LocationType { GRAD,ULICA,JEZERO,REKA,PLAZA,OKEAN, MORE, MOREUZ, MOST,BANJA, - PLANINA, VISORAVAN, PIRAMIDA, LIVADA, SELO, OSTRVO, POLUOSTRVO, KLISURA, ARHIPELAG, - ADA, DELTA, FJORD, GEJZIR, IZVOR, KOTLINA, MINERALNI_IZVOR, PECINA ,SUMA, VODOPAD,VULKAN + PLANINA, VISORAVAN, PIRAMIDA, LIVADA, SELO, OSTRVO, POLUOSTRVO, KLISURA, ARHIPELAG, + ADA, DELTA, FJORD, GEJZIR, IZVOR, KOTLINA, MINERALNI_IZVOR, PECINA ,SUMA, VODOPAD,VULKAN, + MUZEJ,ZAMAK,TRG,SPOMENIK,PARK,ZGRADA } public class Coords diff --git a/Backend/Api/Api/Models/Message.cs b/Backend/Api/Api/Models/Message.cs new file mode 100644 index 0000000..d3b6785 --- /dev/null +++ b/Backend/Api/Api/Models/Message.cs @@ -0,0 +1,27 @@ +using MongoDB.Bson.Serialization.Attributes; +using MongoDB.Bson; + +namespace Api.Models +{ + public class Message + { + [BsonId] + [BsonRepresentation(BsonType.ObjectId)] + public String _id { get; set; } + public String senderId { get; set; } + public String receiverId { get; set; } + public String messagge { get; set; } + public DateTime timestamp { get; set; } + } + public class MessageSend + { + public String senderId { get; set; } + public String messagge { get; set; } + public DateTime timestamp { get; set; } + } + public class MessageReceive + { + public String receiverId { get; set; } + public String messagge { get; set; } + } +} diff --git a/Backend/Api/Api/Models/Post.cs b/Backend/Api/Api/Models/Post.cs index 8099d6c..1a4129f 100644 --- a/Backend/Api/Api/Models/Post.cs +++ b/Backend/Api/Api/Models/Post.cs @@ -18,6 +18,8 @@ namespace Api.Models public List<Rating> ratings { get; set; } public List<Comment> comments { get; set; } public List<File> images { get; set; } + public List<string>? tags { get; set; } + } public class PostReceive { @@ -25,8 +27,7 @@ namespace Api.Models public string locationId { get; set; } public string description { get; set; } public List<IFormFile> images { get; set; } - - + public string? tags { get; set; } } public class PostSend { @@ -39,6 +40,7 @@ namespace Api.Models public double ratings { get; set; } public List<CommentSend> comments { get; set; } public List<File> images { get; set; } + public List<string>? tags { get; set; } } public class Rating { diff --git a/Backend/Api/Api/Models/User.cs b/Backend/Api/Api/Models/User.cs index 2e323a8..6c777e7 100644 --- a/Backend/Api/Api/Models/User.cs +++ b/Backend/Api/Api/Models/User.cs @@ -16,6 +16,11 @@ namespace Api.Models public String password { get; set; } public DateTime creationDate { get; set; } public File? pfp { get; set; } + + public List<string> followers { get; set; } + public List<string> following { get; set; } + public int followersCount { get; set; } + public int followingCount { get; set; } } public class Login @@ -58,5 +63,13 @@ namespace Api.Models public DateTime creationDate { get; set; } public File? pfp { get; set; } public int postcount { get; set; } + + public List<String> followers{ get; set; } + public List<String> following { get; set; } + + public int followersCount { get; set; } + public int followingCount { get; set; } + + } } diff --git a/Backend/Api/Api/Program.cs b/Backend/Api/Api/Program.cs index 7d6b03e..8d22f2b 100644 --- a/Backend/Api/Api/Program.cs +++ b/Backend/Api/Api/Program.cs @@ -27,6 +27,7 @@ builder.Services.AddScoped<IJwtService, JwtService>(); builder.Services.AddScoped<IPostService,PostService>(); builder.Services.AddScoped<IFileService,FileService>(); builder.Services.AddScoped<ILocationService,LocationService>(); +builder.Services.AddScoped<IMessageService, MessageService>(); builder.Services.AddHttpContextAccessor(); @@ -64,6 +65,10 @@ builder.Services.AddSwaggerGen(options => { options.OperationFilter<SecurityRequirementsOperationFilter>(); }); + +builder.Services.AddSignalR(); + + builder.Services.AddCors(options => { options.AddPolicy("CorsPolicy", @@ -84,11 +89,20 @@ if (app.Environment.IsDevelopment()) app.UseSwaggerUI(); } +app.UseWebSockets(new WebSocketOptions +{ + KeepAliveInterval = TimeSpan.FromSeconds(120) +}); //Add Authentication +app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); -app.MapControllers(); +app.UseEndpoints(endpoints => +{ + endpoints.MapControllers(); + endpoints.MapHub<ChatHub>("/chatHub"); +}); app.Run(); diff --git a/Backend/Api/Api/Services/ChatHub.cs b/Backend/Api/Api/Services/ChatHub.cs new file mode 100644 index 0000000..639a585 --- /dev/null +++ b/Backend/Api/Api/Services/ChatHub.cs @@ -0,0 +1,72 @@ +using Api.Interfaces; +using Microsoft.AspNetCore.SignalR; + +namespace Api.Services +{ + public class ChatHub:Hub + { + static public readonly Dictionary<string, string> Users = new Dictionary<string, string>(); + private readonly IJwtService _jwtService; + public ChatHub(IJwtService jwtService) + { + _jwtService = jwtService; + } + public override async Task OnConnectedAsync() + { + string token = Context.GetHttpContext().Request.Headers["access_token"]; + if (token == null) + return; + string id = _jwtService.TokenToId(token); + if (id == null) + return; + Users.Add(Context.ConnectionId, id); + + //await SendDirect(id, "poruka"); + //await Send(Context.ConnectionId); + await base.OnConnectedAsync(); + + } + public override async Task OnDisconnectedAsync(Exception? exception) + { + Users.Remove(Context.ConnectionId); + } + public static List<string> getAllConnectionsOfUser(string id) + { + List<string> keys = new List<string>(); + foreach (var user in Users) + { + if (user.Value == id) + keys.Add(user.Key); + } + return keys; + } + public static bool CheckUser(string id) + { + var users = Users.Values; + foreach (var user in users) + { + if (user == id) + return true; + } + return false; + } + + } +} +//private readonly IHubContext<ChatHub> _ichat; +//await _ichat.Clients.Client(connection).SendAsync("Message",); + +//Message +//SenderId +//meesage +//date + +//Message +//ReceiveId +//meesage + + +//Oba korisnika online poruka se salje preko kontrolera, a stize preko socketa +//Online salje offline poruka se salje preko kontrolera,cuva se u bazi +//Korisnik koji ima poruke a bio je offline salje zahtev kontroleru za preuzimanje poruka +///chatHub
\ No newline at end of file diff --git a/Backend/Api/Api/Services/LocationService.cs b/Backend/Api/Api/Services/LocationService.cs index c91a1b5..afb3b5b 100644 --- a/Backend/Api/Api/Services/LocationService.cs +++ b/Backend/Api/Api/Services/LocationService.cs @@ -31,10 +31,12 @@ namespace Api.Services } public async Task<Location> add(Location loc) { - IEnumerable<Address> adresses = await _geocoder.GeocodeAsync(loc.name+" "+loc.address+" "+loc.city+" "+loc.country); - loc.country = loc.name; - loc.latitude = adresses.First().Coordinates.Latitude; - loc.longitude=adresses.First().Coordinates.Longitude; + + //On Client side + //IEnumerable<Address> adresses = await _geocoder.GeocodeAsync(loc.name+" "+loc.address+" "+loc.city+" "+loc.country); + //loc.country = loc.name; + //loc.latitude = adresses.First().Coordinates.Latitude; + //loc.longitude=adresses.First().Coordinates.Longitude; await _locations.InsertOneAsync(loc); return loc; diff --git a/Backend/Api/Api/Services/MessageService.cs b/Backend/Api/Api/Services/MessageService.cs new file mode 100644 index 0000000..9cc818b --- /dev/null +++ b/Backend/Api/Api/Services/MessageService.cs @@ -0,0 +1,80 @@ +using System.Security.Claims; +using Api.Interfaces; +using Api.Models; +using Microsoft.AspNetCore.SignalR; +using MongoDB.Driver; + +namespace Api.Services +{ + public class MessageService : IMessageService + { + private readonly IHttpContextAccessor _httpContext; + private readonly IMongoCollection<Message> _messages; + private readonly IJwtService _jwtService; + private IConfiguration _configuration; + private readonly IHubContext<ChatHub> _chatHub; + public MessageService(IDatabaseConnection settings, IMongoClient mongoClient, IJwtService jwtService, IHttpContextAccessor httpContextAccessor, IConfiguration configuration,IHubContext<ChatHub> chatHub) + { + var database = mongoClient.GetDatabase(settings.DatabaseName); + _messages = database.GetCollection<Message>(settings.MessageCollectionname); + _jwtService = jwtService; + _httpContext = httpContextAccessor; + _configuration = configuration; + _chatHub = chatHub; + } + public async Task<Message> addMessage(MessageReceive msg) + { + if (_httpContext.HttpContext.User.FindFirstValue("id") == null) + return null; + var senderId = _httpContext.HttpContext.User.FindFirstValue("id").ToString(); + if (senderId == null) + return null; + var tempMsg = new Message(); + tempMsg._id = ""; + tempMsg.receiverId = msg.receiverId; + tempMsg.senderId = senderId; + tempMsg.messagge = msg.messagge; + tempMsg.timestamp = DateTime.Now.ToUniversalTime(); + if (ChatHub.CheckUser(msg.receiverId)) + { + //user online + var temp =messageToMessageSend(tempMsg); + foreach (var connection in ChatHub.getAllConnectionsOfUser(msg.receiverId)) + await _chatHub.Clients.Client(connection).SendAsync("Message",temp); + + } + else + { + //user offline + await _messages.InsertOneAsync(tempMsg); + + } + + + return tempMsg; + } + public MessageSend messageToMessageSend(Message msg) + { + var tempMsg = new MessageSend(); + tempMsg.senderId = msg.senderId; + tempMsg.messagge = msg.messagge; + tempMsg.timestamp = msg.timestamp; + return tempMsg; + } + public async Task<List<MessageSend>> getReceiverMessage() + { + var receiverId = _httpContext.HttpContext.User.FindFirstValue("id").ToString(); + if (receiverId == null) + return null; + var messages = await _messages.Find(msg => msg.receiverId == receiverId).ToListAsync(); + var tempMessages = new List<MessageSend>(); + foreach (var message in messages) + { + tempMessages.Add(messageToMessageSend(message)); + _messages.DeleteOne(msg => msg._id == message._id); + } + return tempMessages; + } + + } +} diff --git a/Backend/Api/Api/Services/PostService.cs b/Backend/Api/Api/Services/PostService.cs index 2d62f49..bdf150b 100644 --- a/Backend/Api/Api/Services/PostService.cs +++ b/Backend/Api/Api/Services/PostService.cs @@ -39,6 +39,8 @@ namespace Api.Services p.comments = new List<Comment>(); p.images = new List<Models.File>(); p.createdAt = DateTime.Now.ToUniversalTime(); + var tags = post.tags.Split("|").ToList(); + p.tags = tags; var folderPath = Path.Combine(Directory.GetCurrentDirectory(), "Files", p.ownerId); if (!Directory.Exists(folderPath)) { @@ -82,6 +84,7 @@ namespace Api.Services p.images = post.images; p.views = post.views.Count(); p.createdAt = post.createdAt; + p.tags = post.tags; if (post.ratings.Count() > 0) { List<int> ratings = new List<int>(); @@ -349,5 +352,21 @@ namespace Api.Services } return tosend; } + public async Task<List<PostSend>> UserHistory(string userid) + { + var posts = await _posts.Find(_ => true).ToListAsync(); + if (posts == null) + return null; + var tosend = new List<PostSend>(); + foreach (var post in posts) + { + if (post.views.Any(x => x.Equals(userid))) + { + var x = await postToPostSend(post); + tosend.Add(x); + } + } + return tosend; + } } } diff --git a/Backend/Api/Api/Services/UserService.cs b/Backend/Api/Api/Services/UserService.cs index 33e6d11..f616d99 100644 --- a/Backend/Api/Api/Services/UserService.cs +++ b/Backend/Api/Api/Services/UserService.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Http; using System.Security.Claims; using MimeKit; using MailKit.Net.Smtp; +using DnsClient; namespace Api.Services { @@ -16,6 +17,8 @@ namespace Api.Services private readonly IJwtService _jwtService; private IConfiguration _configuration; private readonly IFileService _fileService; + + private readonly IMongoCollection<UserSend> _usersSend; public UserService(IDatabaseConnection settings, IMongoClient mongoClient, IJwtService jwtService, IHttpContextAccessor httpContextAccessor, IConfiguration configuration, IFileService fileService) { var database = mongoClient.GetDatabase(settings.DatabaseName); @@ -35,6 +38,7 @@ namespace Api.Services return -2; //username already // user.password = hashPassword(user.password); + await _users.InsertOneAsync(user); return 1; } @@ -375,5 +379,89 @@ namespace Api.Services tosend.postcount = userposts.Count(); return tosend; } + + public async Task<Boolean> AddFollower(string userId,string followerId) + { + User u = await _users.Find(user => user._id==userId).FirstOrDefaultAsync(); + User f = await _users.Find(user => user._id == followerId).FirstOrDefaultAsync(); + + if (userId != null && followerId!=null) + { + if (u.followers == null) + u.followers = new List<string>(); + u.followers.Add(followerId); + if (f.following == null) + f.following = new List<string>(); + f.following.Add(userId); + _users.ReplaceOne(user=>user._id==userId, u); + _users.ReplaceOne(user => user._id == followerId, f); + return true; + } + + + return false; + } + + public async Task<List<UserSend>> GetFollowers(string id) + { + User u = await _users.Find(user => user._id == id).FirstOrDefaultAsync(); + List<UserSend> followers = new List<UserSend>(); + if (u != null) + { + //List<UserSend> followers = u.followers; + if (u.followers!=null &&u.followers.Count() > 0) + { + foreach (string userid in u.followers) + { + User utemp = await _users.Find(user => user._id == userid).FirstOrDefaultAsync(); + if (utemp == null) + { + continue; + } + UserSend follower = new UserSend(); + follower.pfp = utemp.pfp; + follower.username = utemp.username; + follower.email = utemp.username; + follower.followers = utemp.followers; + follower._id = utemp._id; + + followers.Add((UserSend)follower); + } + } + return followers; + } + return null; + } + + public async Task<List<UserSend>> GetFollowing(string id) + { + User u = await _users.Find(user => user._id == id).FirstOrDefaultAsync(); + List<UserSend> following = new List<UserSend>(); + if (u != null) + { + + if (u.following!=null &&u.following.Count() > 0) + { + foreach (string userid in u.following) + { + User utemp = await _users.Find(user => user._id == userid).FirstOrDefaultAsync(); + if (utemp == null) + { + continue; + } + UserSend follower = new UserSend(); + follower.pfp = utemp.pfp; + follower.username = utemp.username; + follower.email = utemp.username; + follower.followers = utemp.followers; + follower._id = utemp._id; + + following.Add((UserSend)follower); + } + } + return following; + } + return null; + } } } diff --git a/Backend/Api/Api/appsettings.json b/Backend/Api/Api/appsettings.json index a3ef323..7dbaa6a 100644 --- a/Backend/Api/Api/appsettings.json +++ b/Backend/Api/Api/appsettings.json @@ -21,7 +21,8 @@ "UserCollectionName": "users", "PostCollectionName": "posts", "FileCollectionName": "files", - "LocationCollectionname": "locations" + "LocationCollectionname": "locations", + "MessageCollectionname": "messages" }, "EmailCfg": { |