using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore; using Microsoft.Net.Http.Headers; using Teso_API.Models; using System.Linq; using Google.Cloud.Firestore; using Google.Apis.Auth.OAuth2; using Newtonsoft.Json; using Grpc.Auth; namespace Teso_API.Controllers { [AllowAnonymous, Route("relationships")] [ApiController] public class RelationsController : ControllerBase { private readonly TESOContext _context; private FirestoreDb db; public RelationsController(TESOContext context) { _context = context; //db = FirestoreDb.Create("teso-ghana"); db = new FirestoreDbBuilder { ProjectId = ServerLocation.credentials.project_id, ChannelCredentials = GoogleCredential.FromJson(JsonConvert.SerializeObject(ServerLocation.credentials)).ToChannelCredentials(), }.Build(); } public async Task> GetRelationships(string userID, string type) { var param = new SqlParameter[] { new SqlParameter() { ParameterName = "@userGUID", SqlDbType = System.Data.SqlDbType.VarChar, Size = 100, Direction = System.Data.ParameterDirection.Input, Value = userID }, new SqlParameter() { ParameterName = "@Status", SqlDbType = System.Data.SqlDbType.VarChar, Direction = System.Data.ParameterDirection.Input, Value = "approved" }, new SqlParameter() { ParameterName = "@Type", SqlDbType = System.Data.SqlDbType.VarChar, Direction = System.Data.ParameterDirection.Input, Value = type }, }; return await _context.Relationships.FromSqlRaw("Select * from Relations r where r.userGUID <> @userGUID and r.relation_id in (Select relation_id from RelationsDetail " + "where (beneficiary_recipient = @userGUID and status = @status and relation_type = @Type) or (beneficiary_requester = @userGUID and status = @status and relation_type = @Type))", param).ToListAsync(); } [Authorize] [Route("friends"), HttpGet] public async Task> GetFriends() { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; List fetched = await GetRelationships(userID, "TSR01"); List friendsList = new List(); foreach (Relations relations in fetched) { TesoUserDetail detail = await _context.TesoUserDetails.AsQueryable().Where(usr => usr.UserGUID == relations.UserGuid).FirstOrDefaultAsync(); int friends = await _context.Relationships.AsQueryable().Where(t => t.UserGuid == relations.UserGuid).CountAsync(); UserFinance finance = await _context.UserFinances.AsQueryable().Where(usr => usr.UserGUID == relations.UserGuid).FirstOrDefaultAsync(); if (finance == null) { finance = new UserFinance(); finance.Gold = 0; finance.Silver = 0; } TesoUser tesouser = new TesoUser(); tesouser.userGUID = detail.UserGUID; tesouser.username = detail.Username; tesouser.firstname = detail.Firstname; tesouser.lastname = detail.Surname; tesouser.description = detail.Description; tesouser.email = detail.Email; tesouser.phonenumber = detail.Phonenumber.HasValue ? detail.Phonenumber.Value.ToString() : ""; tesouser.address = detail.Address; tesouser.thumbnail_dp = detail.ThumbnailDp; tesouser.country = detail.Country; tesouser.gender = detail.Gender; tesouser.gold = finance.Gold.ToString(); tesouser.silver = finance.Silver.ToString(); tesouser.friends = friends.ToString(); friendsList.Add(tesouser); } return friendsList; } [Authorize] [Route("related"), HttpPost] public async Task GetRelation([FromBody] string tesoUser) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; List relatives = await GetRelationships(userID, "TSR01"); if (relatives.Any(f => f.UserGuid == tesoUser)) { return Ok(true); } else { return Ok(false); } } [Authorize] [Route("unfriend"), HttpPost] public async Task RemoveRelation([FromBody] string tesoUser) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; List relatives = await GetRelationships(userID, "TSR01"); Relations relations = relatives.Where(r => r.UserGuid == tesoUser).FirstOrDefault(); List toDelete = await _context.Relationships.AsQueryable().Where(r => r.RelationId == relations.RelationId).ToListAsync(); RelationsDetail detail = await _context.RelationsDetails.AsQueryable().Where(r => r.RelationId == relations.RelationId).FirstOrDefaultAsync(); detail.Status = "cancelled"; _context.Relationships.RemoveRange(toDelete); _context.Entry(detail).State = EntityState.Modified; try { await _context.SaveChangesAsync(); return Ok(); } catch (DbUpdateException) { return Conflict(); } } /// /// FireStore Notifications add friend request /// [Authorize] [Route("friendrequest"), HttpPost] public async Task RequestRelation([FromBody] string tesoUser) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; RelationsDetail detail = new RelationsDetail(); detail.RelationId = DateTime.Now.ToString("yyyyMMddHHmmssfff") + userID + tesoUser; detail.Status = "pending"; detail.RequestDate = DateTime.Now; detail.RelationType = await _context.RelationTypes.AsQueryable().Where(r => r.TypeName == "friends").Select(t => t.TypeCode).FirstOrDefaultAsync(); detail.BeneficiaryRecipient = tesoUser; detail.BeneficiaryRequester = userID; _context.RelationsDetails.Add(detail); try { await _context.SaveChangesAsync(); TesoUserDetail requester = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == userID).FirstOrDefaultAsync(); TesoUserDetail recipient = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == tesoUser).FirstOrDefaultAsync(); DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(tesoUser).Collection(tesoUser).Document(detail.RelationId); Dictionary user = new Dictionary { { "notificationType", "friendrequest" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "initiatorID", userID }, { "relationID", detail.RelationId }, { "initiatorUsername", requester.Username }, { "initiatorFirstname", requester.Firstname }, { "initiatorSurname", requester.Surname }, {"initiatorThumbnail",requester.ThumbnailDp }, {"recipient",tesoUser }, }; await docRef.SetAsync(user); return Ok(); } catch (DbUpdateException) { return Conflict(); } } [Authorize] [Route("sent"), HttpPost] public async Task GetPending([FromBody] string tesoUser) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; if (_context.RelationsDetails.Any(f => f.BeneficiaryRequester == userID && f.BeneficiaryRecipient == tesoUser && f.Status == "pending")) { return Ok(true); } else { return Ok(false); } } [Authorize] [Route("received"), HttpPost] public async Task GetReceived([FromBody] string tesoUser) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; bool received = _context.RelationsDetails.Any(f => f.BeneficiaryRequester == tesoUser && f.BeneficiaryRecipient == userID && f.Status == "pending"); if (received) { return Ok(true); } else { return Ok(false); } } /// /// Firestore notifications remove request /// [Authorize] [Route("friendapproval"), HttpPost] public async Task ApprovalRelation([FromBody] string tesoUser) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; RelationsDetail detail = await _context.RelationsDetails.AsQueryable().Where(d => d.BeneficiaryRequester == tesoUser && d.BeneficiaryRecipient == userID && d.Status == "pending").FirstOrDefaultAsync(); detail.Status = "approved"; detail.ApprovalDate = DateTime.Now; _context.Entry(detail).State = EntityState.Modified; Relations relation1 = new Relations(); Relations relation2 = new Relations(); relation1.RelationId = detail.RelationId; relation1.UserGuid = userID; relation1.CountId = DateTime.Now.ToString("yyyyMMddHHmmssfff") + userID; relation2.RelationId = detail.RelationId; relation2.UserGuid = tesoUser; relation2.CountId = DateTime.Now.ToString("yyyyMMddHHmmssfff") + tesoUser; List relationshipsAll = new List(); relationshipsAll.Add(relation1); relationshipsAll.Add(relation2); _context.Relationships.AddRange(relationshipsAll); try { await _context.SaveChangesAsync(); TesoUserDetail requester = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == userID).FirstOrDefaultAsync(); DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(userID).Collection(userID).Document(detail.RelationId); DocumentReference docRef1 = db.Collection(ServerLocation.user_notifications).Document(tesoUser).Collection(tesoUser).Document(detail.RelationId); Dictionary user = new Dictionary { { "notificationType", "friendapproval" }, { "relationID", detail.RelationId }, { "timestamp", new DateTimeOffset(DateTime.Now).ToUnixTimeMilliseconds()}, { "initiatorID", userID }, { "initiatorUsername", requester.Username }, { "initiatorFirstname", requester.Firstname }, { "initiatorSurname", requester.Surname }, {"initiatorThumbnail",requester.ThumbnailDp }, {"recipient",tesoUser }, }; await docRef1.SetAsync(user); await docRef.DeleteAsync(); return Ok(); } catch (Exception ez) { Console.WriteLine(ez.ToString()); return Conflict(); } } /// /// Firestore notifications remove request /// [Authorize] [Route("frienddecline"), HttpPost] public async Task DeclineRelationRequest([FromBody] string tesoUser) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; RelationsDetail detail = await _context.RelationsDetails.AsQueryable().Where(r => r.BeneficiaryRecipient == userID && r.BeneficiaryRequester == tesoUser && r.Status == "pending").FirstOrDefaultAsync(); detail.Status = "declined"; _context.Entry(detail).State = EntityState.Modified; try { await _context.SaveChangesAsync(); DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(userID).Collection(userID).Document(detail.RelationId); await docRef.DeleteAsync(); return Ok(); } catch (DbUpdateException) { return Conflict(); } } /// /// Firestore notifications remove request /// [Authorize] [Route("cancelrequest"), HttpPost] public async Task CancelRelationRequest([FromBody] string tesoUser) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; RelationsDetail detail = await _context.RelationsDetails.AsQueryable().Where(r => r.BeneficiaryRequester == userID && r.BeneficiaryRecipient == tesoUser && r.Status == "pending").FirstOrDefaultAsync(); detail.Status = "cancelled"; _context.Entry(detail).State = EntityState.Modified; try { await _context.SaveChangesAsync(); DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(tesoUser).Collection(tesoUser).Document(detail.RelationId); await docRef.DeleteAsync(); return Ok(); } catch (DbUpdateException) { return Conflict(); } } [Authorize] [Route("business-subscription"), HttpPost] public async Task Subscribe([FromBody] string businessID) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; RelationsDetail detail = new RelationsDetail(); detail.RelationId = DateTime.Now.ToString("yyyyMMddHHmmssfff") + userID + businessID; detail.Status = "subscribed"; detail.RequestDate = DateTime.Now; detail.RelationType = await _context.RelationTypes.AsQueryable().Where(r => r.TypeName == "Follower").Select(t => t.TypeCode).FirstOrDefaultAsync(); detail.BeneficiaryRecipient = businessID; detail.BeneficiaryRequester = userID; detail.ApprovalDate = DateTime.Now; _context.RelationsDetails.Add(detail); try { await _context.SaveChangesAsync(); TesoBusinessDetail recipient = await _context.TesoBusinessDetails.AsQueryable().Where(i => i.BusinessId == businessID).FirstOrDefaultAsync(); TesoUserDetail requester = await _context.TesoUserDetails.AsQueryable().Where(i => i.UserGUID == userID).FirstOrDefaultAsync(); DocumentReference docRef = db.Collection(ServerLocation.business_notifications).Document(businessID).Collection(businessID).Document(detail.RelationId); Dictionary user = new Dictionary { { "notificationType", "subscription" }, { "timestamp", new DateTimeOffset(DateTimeOffset.UtcNow.DateTime).ToUnixTimeMilliseconds()}, { "subscriber", userID }, { "relationID", detail.RelationId }, { "initiatorUsername", requester.Username }, { "initiatorFirstname", requester.Firstname }, { "initiatorSurname", requester.Surname }, {"initiatorThumbnail",requester.ThumbnailDp }, }; await docRef.SetAsync(user); return Ok(); } catch (DbUpdateException) { return Conflict(); } } /// /// Firestore notifications remove subscription /// [Authorize] [Route("business-unsubscribe"), HttpPost] public async Task Unsubscribe([FromBody] string businessID) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; RelationsDetail detail = await _context.RelationsDetails.AsQueryable().Where(r => r.BeneficiaryRecipient == businessID && r.BeneficiaryRequester == userID) .FirstOrDefaultAsync(); detail.Status = "cancelled"; try { await _context.SaveChangesAsync(); DocumentReference docRef = db.Collection(ServerLocation.business_notifications).Document(businessID).Collection(businessID).Document(detail.RelationId); await docRef.DeleteAsync(); return Ok(); } catch (DbUpdateException) { return Conflict(); } } [Authorize] [Route("business-following"), HttpPost] public async Task Following([FromBody] string businessID) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; RelationsDetail detail = await _context.RelationsDetails.AsQueryable().Where(r => r.BeneficiaryRecipient == businessID && r.BeneficiaryRequester == userID && r.Status != "cancelled").FirstOrDefaultAsync(); try { if (detail != null) { return Ok("subscribed"); } else { return Ok("not-subscribe"); } } catch { return BadRequest(); } } [Authorize] [Route("block"), HttpPost] public async Task BlockUser([FromBody] string targetUID) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; _context.BlockedUsers.Add(new BlockedUser { Initiator = userID, Target = targetUID, Timestamp = DateTime.Now }); RelationsDetail detail; RelationsDetail detail2; RelationsDetail detail3; List relatives = await GetRelationships(userID, "TSR01"); WriteBatch batch = db.StartBatch(); DocumentReference chats = db.Collection("messages").Document(userID + targetUID); DocumentReference chats2 = db.Collection("messages").Document(targetUID + userID); DocumentReference lastmessageA = db.Collection("inbox").Document(userID).Collection("lastMessage").Document(userID + targetUID); DocumentReference lastmessageB = db.Collection("inbox").Document(userID).Collection("lastMessage").Document(targetUID + userID); DocumentReference lastmessage2A = db.Collection("inbox").Document(userID).Collection("lastMessage").Document(userID + targetUID); DocumentReference lastmessage2B = db.Collection("inbox").Document(userID).Collection("lastMessage").Document(targetUID+ userID); batch.Delete(chats); batch.Delete(chats2); batch.Delete(lastmessageA); batch.Delete(lastmessageB); batch.Delete(lastmessage2A); batch.Delete(lastmessage2B); Relations relations = relatives.Where(r => r.UserGuid == targetUID).FirstOrDefault(); if (relations != null) { detail = await _context.RelationsDetails.AsQueryable().Where(r => r.BeneficiaryRecipient == userID && r.BeneficiaryRequester == targetUID && r.Status == "pending").FirstOrDefaultAsync(); if (detail != null) { detail.Status = "blocked"; _context.Entry(detail).State = EntityState.Modified; DocumentReference docRef = db.Collection(ServerLocation.user_notifications).Document(userID).Collection(userID).Document(detail.RelationId); batch.Delete(docRef); } detail2 = await _context.RelationsDetails.AsQueryable().Where(r => r.BeneficiaryRecipient == targetUID && r.BeneficiaryRequester == userID && r.Status == "pending").FirstOrDefaultAsync(); if (detail2 != null) { detail2.Status = "blocked"; _context.Entry(detail2).State = EntityState.Modified; } List toDelete = await _context.Relationships.AsQueryable().Where(r => r.RelationId == relations.RelationId).ToListAsync(); _context.Relationships.RemoveRange(toDelete); detail3 = await _context.RelationsDetails.AsQueryable().Where(r => r.RelationId == relations.RelationId).FirstOrDefaultAsync(); if (detail3 != null) { detail3.Status = "blocked"; _context.Entry(detail3).State = EntityState.Modified; } } try { await _context.SaveChangesAsync(); await batch.CommitAsync(); return Ok(); } catch (DbUpdateException) { return Conflict(); } } [Authorize] [Route("unblock"), HttpPost] public async Task UnBlockUser([FromBody] string targetUID) { var accessToken = Request.Headers[HeaderNames.Authorization]; string token = accessToken; token = token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadToken(token) as JwtSecurityToken; string userID = jwtToken.Claims.First(claim => claim.Type == "userGUID").Value; BlockedUser userBlocked = await _context.BlockedUsers.AsQueryable().Where(x => x.Target == targetUID && x.Initiator == userID).FirstOrDefaultAsync(); _context.BlockedUsers.Remove(userBlocked); try { await _context.SaveChangesAsync(); return Ok(); } catch (DbUpdateException) { return Conflict(); } } } }