Backend for the Teso project written in 2022
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

620 lines
27 KiB

3 months ago
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<List<Relations>> 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<IEnumerable<TesoUser>> 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<Relations> fetched = await GetRelationships(userID, "TSR01");
List<TesoUser> friendsList = new List<TesoUser>();
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<ActionResult> 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<Relations> 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<ActionResult> 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<Relations> relatives = await GetRelationships(userID, "TSR01");
Relations relations = relatives.Where(r => r.UserGuid == tesoUser).FirstOrDefault();
List<Relations> 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();
}
}
/// <summary>
/// FireStore Notifications add friend request
/// </summary>
[Authorize]
[Route("friendrequest"), HttpPost]
public async Task<ActionResult> 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<string, object> user = new Dictionary<string, object>
{
{ "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<ActionResult> 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<ActionResult> 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);
}
}
/// <summary>
/// Firestore notifications remove request
/// </summary>
[Authorize]
[Route("friendapproval"), HttpPost]
public async Task<ActionResult> 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<Relations> relationshipsAll = new List<Relations>();
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<string, object> user = new Dictionary<string, object>
{
{ "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();
}
}
/// <summary>
/// Firestore notifications remove request
/// </summary>
[Authorize]
[Route("frienddecline"), HttpPost]
public async Task<ActionResult> 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();
}
}
/// <summary>
/// Firestore notifications remove request
/// </summary>
[Authorize]
[Route("cancelrequest"), HttpPost]
public async Task<ActionResult> 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<ActionResult> 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<string, object> user = new Dictionary<string, object>
{
{ "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();
}
}
/// <summary>
/// Firestore notifications remove subscription
/// </summary>
[Authorize]
[Route("business-unsubscribe"), HttpPost]
public async Task<ActionResult> 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<ActionResult> 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<ActionResult> 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<Relations> 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<Relations> 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<ActionResult> 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();
}
}
}
}