Refactor Some Endpoints To Work With Client V2
This commit is contained in:
parent
4117727b68
commit
98f7c4cd96
@ -101,6 +101,15 @@ namespace qtc_api.Controllers
|
||||
|
||||
var token = await _tokenService.GenerateAccessTokenAndRefreshToken(dbUser.Data, true, request.RememberMe);
|
||||
|
||||
// check if the new user tag can be removed (14 days or 2 weeks)
|
||||
var now = DateTime.UtcNow;
|
||||
if(now.Date > dbUser.Data.CreatedAt.Date.AddDays(14) && dbUser.Data.Tags.Contains("new_user"))
|
||||
{
|
||||
List<string> _tagsList = [.. dbUser.Data.Tags];
|
||||
_tagsList.Remove("new_user");
|
||||
dbUser.Data.Tags = [.. _tagsList];
|
||||
}
|
||||
|
||||
await dataContext.SaveChangesAsync();
|
||||
return Ok(token);
|
||||
}
|
||||
|
||||
32
qtc-net-server/Controllers/TagController.cs
Normal file
32
qtc-net-server/Controllers/TagController.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Razor.TagHelpers;
|
||||
using qtc_api.Services.BucketService;
|
||||
|
||||
namespace qtc_api.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/tags")]
|
||||
public class TagController : ControllerBase
|
||||
{
|
||||
private readonly IBucketService _bucketService;
|
||||
public TagController(IBucketService bucketService)
|
||||
{
|
||||
_bucketService = bucketService;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("{tagName}")]
|
||||
[Authorize]
|
||||
public async Task<ActionResult> GetTagPicBytes(string tagName)
|
||||
{
|
||||
var _s3Res = await _bucketService.GetTagImageBytes(tagName);
|
||||
if (_s3Res != null)
|
||||
return new FileContentResult(_s3Res, "image/jpeg");
|
||||
else
|
||||
{
|
||||
return NotFound(); // TODO - code the legacy way of finding images here (mostly for self-hosters)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -73,10 +73,15 @@ namespace qtc_api.Controllers
|
||||
if(id != null && id == user.Id)
|
||||
{
|
||||
var updatedUser = await _userService.UpdateUserInfo(user);
|
||||
|
||||
if (updatedUser.Success && updatedUser.Data != null)
|
||||
{
|
||||
await _chatGWContext.Clients.All.SendAsync("RefreshUserLists");
|
||||
await _chatGWContext.Clients.All.SendAsync("RefreshContactsList");
|
||||
await _chatGWContext.Clients.User(updatedUser.Data.Id).SendAsync("UpdateCurrentUser");
|
||||
|
||||
return Ok(updatedUser);
|
||||
}
|
||||
else return Ok();
|
||||
} else
|
||||
{
|
||||
return Unauthorized("You are not authorized to edit that user.");
|
||||
@ -116,6 +121,7 @@ namespace qtc_api.Controllers
|
||||
stream.CopyTo(ms);
|
||||
await _cache.SetImageAsync(recordId, ms.ToArray(), TimeSpan.FromHours(1));
|
||||
|
||||
await _chatGWContext.Clients.User(id).SendAsync("UpdateCurrentUser");
|
||||
return Ok(response);
|
||||
} else
|
||||
{
|
||||
@ -185,8 +191,12 @@ namespace qtc_api.Controllers
|
||||
{
|
||||
IEnumerable<Claim> claims = identity.Claims;
|
||||
var id = claims.First().Value;
|
||||
|
||||
if (id != null) return Ok(await _userService.AddCurrencyToUser(id, amount, isSpinClaim));
|
||||
var _res = await _userService.AddCurrencyToUser(id, amount, isSpinClaim);
|
||||
if(_res.Success)
|
||||
{
|
||||
await _chatGWContext.Clients.User(id).SendAsync("UpdateCurrentUser");
|
||||
return Ok(_res);
|
||||
}
|
||||
else return Ok(new ServiceResponse<int> { Success = false, Message = "Identity Has No User ID" });
|
||||
}
|
||||
else return Ok(new ServiceResponse<int> { Success = false, Message = "No Identity" });
|
||||
|
||||
@ -13,5 +13,7 @@
|
||||
public int Status { get; set; } = 0;
|
||||
public int CurrencyAmount { get; set; } = 0;
|
||||
public int ProfileCosmeticId { get; set; } = 0;
|
||||
public string TextStatus { get; set; } = string.Empty;
|
||||
public string[] Tags { get; set; } = [];
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,5 +7,6 @@
|
||||
public string Bio { get; set; } = string.Empty;
|
||||
public DateTime DateOfBirth { get; set; } = new DateTime();
|
||||
public int ProfileCosmeticId { get; set; } = 0;
|
||||
public string TextStatus { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using qtc_api.Services.RoomService;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using qtc_api.Services.RoomService;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace qtc_api.Hubs
|
||||
@ -9,17 +10,25 @@ namespace qtc_api.Hubs
|
||||
private IRoomService _roomService;
|
||||
private ILogger<ChatHub> _logger;
|
||||
private DataContext _dataContext;
|
||||
private ServerConfig _serverConfig;
|
||||
|
||||
private static readonly Dictionary<string, List<User>> GroupUsers = [];
|
||||
private static readonly Dictionary<string, List<string>> ConnectedUsers = [];
|
||||
private static readonly List<User> OnlineUsers = [];
|
||||
public static readonly Dictionary<string, List<User>> GroupUsers = [];
|
||||
public static readonly Dictionary<string, List<string>> ConnectedUsers = [];
|
||||
public static readonly List<User> OnlineUsers = [];
|
||||
|
||||
public ChatHub(IUserService userService, IRoomService roomService, ILogger<ChatHub> logger, DataContext dataContext)
|
||||
private static User ServerUser = new()
|
||||
{
|
||||
Id = "0",
|
||||
Username = "Server",
|
||||
};
|
||||
|
||||
public ChatHub(IUserService userService, IRoomService roomService, ILogger<ChatHub> logger, DataContext dataContext, ServerConfig serverConfig)
|
||||
{
|
||||
_userService = userService;
|
||||
_roomService = roomService;
|
||||
_logger = logger;
|
||||
_dataContext = dataContext;
|
||||
_serverConfig = serverConfig;
|
||||
}
|
||||
|
||||
public async override Task OnConnectedAsync()
|
||||
@ -52,6 +61,7 @@ namespace qtc_api.Hubs
|
||||
if (user.Data.Status == 0) await UpdateStatusAsync(user.Data, 1);
|
||||
|
||||
await Clients.Client(Context.ConnectionId).SendAsync("RefreshRoomList");
|
||||
await Clients.Client(Context.ConnectionId).SendAsync("ReceiveServerConfig", _serverConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -117,6 +127,7 @@ namespace qtc_api.Hubs
|
||||
await Clients.All.SendAsync("RefreshUserLists");
|
||||
await Clients.All.SendAsync("RefreshContactsList");
|
||||
Log($"Status Was Set To {res.Data.Status} On User {user.Username}");
|
||||
await Clients.Client(Context.ConnectionId).SendAsync("UpdateCurrentUser");
|
||||
}
|
||||
else
|
||||
Log($"Something Went Wrong Setting The Status On User {user.Username}");
|
||||
@ -128,12 +139,12 @@ namespace qtc_api.Hubs
|
||||
{
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, room.Id);
|
||||
|
||||
await Clients.Group(room.Id).SendAsync("RoomMessage", $"Server: User {user.Username} Has Joined {room.Name}");
|
||||
await Clients.Group(room.Id).SendAsync("RoomMessage", ServerUser, $"User {user.Username} Has Joined {room.Name}", room);
|
||||
|
||||
if (!GroupUsers.TryGetValue(room.Id, out _)) { GroupUsers.Add(room.Id, new List<User>()); }
|
||||
GroupUsers[room.Id].Add(user);
|
||||
|
||||
await Clients.Group(room.Id).SendAsync("RoomUserList", GroupUsers[room.Id]);
|
||||
await Clients.Group(room.Id).SendAsync("RoomUserList", room, GroupUsers[room.Id]);
|
||||
Log($"User {user.Username} Has Joined {room.Name}");
|
||||
|
||||
user.CurrentRoomId = room.Id;
|
||||
@ -157,7 +168,7 @@ namespace qtc_api.Hubs
|
||||
{
|
||||
await Groups.AddToGroupAsync(Context.ConnectionId, room.Data.Id);
|
||||
|
||||
await Clients.Group(room.Data.Id).SendAsync("GuestJoin", username);
|
||||
await Clients.Group(room.Data.Id).SendAsync("RoomMessage", ServerUser, $"Guest User {username} Has Joined {room.Data.Name}", room);
|
||||
|
||||
room.Data.UserCount += 1;
|
||||
await _dataContext.SaveChangesAsync();
|
||||
@ -172,11 +183,11 @@ namespace qtc_api.Hubs
|
||||
{
|
||||
await Groups.RemoveFromGroupAsync(Context.ConnectionId, room.Id);
|
||||
|
||||
await Clients.Group(room.Id).SendAsync("RoomMessage", $"Server: User {user.Username} Has Left {room.Name}");
|
||||
await Clients.Group(room.Id).SendAsync("RoomMessage", ServerUser, $"User {user.Username} Has Left {room.Name}", room);
|
||||
|
||||
if (GroupUsers.TryGetValue(room.Id, out _)) GroupUsers[room.Id].Remove(GroupUsers[room.Id].FirstOrDefault(e => e.Id == user.Id)!);
|
||||
|
||||
await Clients.Group(room.Id).SendAsync("RoomUserList", GroupUsers[room.Id]);
|
||||
await Clients.Group(room.Id).SendAsync("RoomUserList", room, GroupUsers[room.Id]);
|
||||
Log($"User {user.Username} Has Left {room.Name}");
|
||||
|
||||
user.CurrentRoomId = string.Empty;
|
||||
@ -194,7 +205,7 @@ namespace qtc_api.Hubs
|
||||
[Authorize]
|
||||
public async Task SendMessageAsync(User user, Message message, Room room)
|
||||
{
|
||||
await Clients.Group(room.Id).SendAsync("RoomMessage", $"{user.Username}: {message.Content}");
|
||||
await Clients.Group(room.Id).SendAsync("RoomMessage", user, $"{message.Content}", room);
|
||||
}
|
||||
|
||||
[HubMethodName("SendDirectMessage")]
|
||||
@ -207,7 +218,7 @@ namespace qtc_api.Hubs
|
||||
var connection = value.FirstOrDefault();
|
||||
if(connection != null)
|
||||
{
|
||||
UserInformationDto userInformationDto = new UserInformationDto { Id = user.Id, Username = user.Username, Bio = user.Bio, Role = user.Role, Status = user.Status, CreatedAt = user.CreatedAt, DateOfBirth = user.DateOfBirth, ProfilePicture = user.ProfilePicture };
|
||||
UserInformationDto userInformationDto = new UserInformationDto { Id = user.Id, Username = user.Username, Bio = user.Bio, Role = user.Role, Status = user.Status, CreatedAt = user.CreatedAt, DateOfBirth = user.DateOfBirth, ProfilePicture = user.ProfilePicture, ProfileCosmeticId = user.ActiveProfileCosmetic };
|
||||
await Clients.Client(connection).SendAsync("ReceiveDirectMessage", message, userInformationDto);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
public int ActiveProfileCosmetic { get; set; } = 0;
|
||||
public string CurrentRoomId { get; set; } = string.Empty;
|
||||
public DateTime LastLogin { get; set; }
|
||||
public string TextStatus { get; set; } = string.Empty;
|
||||
public string[] Tags { get; set; } = [];
|
||||
|
||||
public virtual IEnumerable<RefreshToken>? RefreshTokens { get; }
|
||||
public virtual IEnumerable<Contact>? ContactsMade { get; }
|
||||
|
||||
@ -19,6 +19,7 @@ using qtc_api.Services.GameRoomService;
|
||||
using qtc_api.Services.StoreService;
|
||||
using qtc_api.Services.EmailService;
|
||||
using qtc_api.Services.BucketService;
|
||||
using System.Text.Json;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@ -68,6 +69,28 @@ builder.Services.AddScoped<IRoomService, RoomService>();
|
||||
builder.Services.AddScoped<IContactService, ContactService>();
|
||||
builder.Services.AddScoped<StoreService>();
|
||||
builder.Services.AddScoped<IBucketService, BucketService>();
|
||||
builder.Services.AddScoped(provider => GetServerConfig());
|
||||
|
||||
ServerConfig GetServerConfig()
|
||||
{
|
||||
if (!File.Exists("./Resources/ServerConfig.json"))
|
||||
throw new Exception("Server Config Doesn't Exist. Please Refer To The Repo For Examples.");
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
var _jsonText = File.ReadAllText("./Resources/ServerConfig.json");
|
||||
ServerConfig? _config = JsonSerializer.Deserialize<ServerConfig>(_jsonText);
|
||||
if (_config != null)
|
||||
return _config;
|
||||
else throw new Exception("Invalid Server Config. Please Refer To The Repo For Examples.");
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
throw new Exception("Invalid Server Config. Please Refer To The Repo For Examples.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder.Services.AddSingleton<CurrencyGamesService>();
|
||||
builder.Services.AddSingleton<GameRoomService>();
|
||||
|
||||
@ -11,6 +11,7 @@ namespace qtc_api.Services.BucketService
|
||||
public string AccessKey { get; private set; }
|
||||
public string SecretKey { get; private set; }
|
||||
public string ProfileImagesBucketName { get; private set; }
|
||||
public string CDNBucketName { get; private set; }
|
||||
public string ImagesBucketName { get; private set; }
|
||||
|
||||
private static AmazonS3Client S3Client;
|
||||
@ -27,6 +28,7 @@ namespace qtc_api.Services.BucketService
|
||||
var accessKey = _config["S3Config:S3AccessKey"];
|
||||
var secretKey = _config["S3Config:S3SecretKey"];
|
||||
var profileImagesBucket = _config["S3Config:S3ProfileImagesBucket"];
|
||||
var cdnBucket = _config["S3Config:S3CDNBucket"];
|
||||
var imagesBucket = _config["S3Config:S3ImagesBucket"];
|
||||
var enabled = _config.GetValue<bool>("S3Config:S3Enabled");
|
||||
|
||||
@ -34,6 +36,7 @@ namespace qtc_api.Services.BucketService
|
||||
if (accessKey != null) AccessKey = accessKey;
|
||||
if (secretKey != null) SecretKey = secretKey;
|
||||
if (profileImagesBucket != null) ProfileImagesBucketName = profileImagesBucket;
|
||||
if (cdnBucket != null) CDNBucketName = cdnBucket;
|
||||
if (imagesBucket != null) ImagesBucketName = imagesBucket;
|
||||
|
||||
Enabled = enabled;
|
||||
@ -89,12 +92,37 @@ namespace qtc_api.Services.BucketService
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
using (var stream = response.ResponseStream)
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
using var stream = response.ResponseStream;
|
||||
using var ms = new MemoryStream();
|
||||
stream.CopyTo(ms);
|
||||
return ms.ToArray();
|
||||
}
|
||||
else return default;
|
||||
} catch (AmazonS3Exception ex)
|
||||
{
|
||||
_logger.LogError($"S3 Bucket Threw An Exception\n{ex.Message}\n{ex.StackTrace}");
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<byte[]?> GetTagImageBytes(string tagName)
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
_logger.LogWarning("Not Using S3 Bucket. Performance May Be Degraded.");
|
||||
return default;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var response = await S3Client.GetObjectAsync(CDNBucketName, $@"tags/{tagName}.png");
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
using var stream = response.ResponseStream;
|
||||
using var ms = new MemoryStream();
|
||||
stream.CopyTo(ms);
|
||||
return ms.ToArray();
|
||||
}
|
||||
else return default;
|
||||
} catch (AmazonS3Exception ex)
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
public string ImagesBucketName { get; }
|
||||
public Task<bool> PutProfileImage(string userId, string imageName, byte[] imageBytes);
|
||||
public Task<byte[]?> GetProfileImageBytes(string userId, string imageName);
|
||||
public Task<byte[]?> GetTagImageBytes(string tagName);
|
||||
public Task<bool> DeleteProfileImage(string userId, string imageName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,9 @@ namespace qtc_api.Services.UserService
|
||||
user.Role = _configuration["Jwt:DefaultUserRole"]!;
|
||||
user.CreatedAt = DateTime.UtcNow;
|
||||
|
||||
// add new user tag
|
||||
user.Tags = ["new_user"];
|
||||
|
||||
try
|
||||
{
|
||||
var cUser = userList.FirstOrDefault(x => x.Email == user.Email);
|
||||
@ -174,19 +177,30 @@ namespace qtc_api.Services.UserService
|
||||
|
||||
if(user != null)
|
||||
{
|
||||
var dto = new UserInformationDto();
|
||||
var dto = new UserInformationDto
|
||||
{
|
||||
Id = user.Id,
|
||||
Username = user.Username,
|
||||
ProfilePicture = user.ProfilePicture,
|
||||
Role = user.Role,
|
||||
Bio = user.Bio,
|
||||
DateOfBirth = user.DateOfBirth,
|
||||
CreatedAt = user.CreatedAt,
|
||||
Status = user.Status,
|
||||
CurrencyAmount = user.CurrencyAmount,
|
||||
ProfileCosmeticId = user.ActiveProfileCosmetic,
|
||||
LastLogin = user.LastLogin,
|
||||
TextStatus = user.TextStatus,
|
||||
Tags = user.Tags
|
||||
};
|
||||
|
||||
dto.Id = user.Id;
|
||||
dto.Username = user.Username;
|
||||
dto.ProfilePicture = user.ProfilePicture;
|
||||
dto.Role = user.Role;
|
||||
dto.Bio = user.Bio;
|
||||
dto.DateOfBirth = user.DateOfBirth;
|
||||
dto.CreatedAt = user.CreatedAt;
|
||||
dto.Status = user.Status;
|
||||
dto.CurrencyAmount = user.CurrencyAmount;
|
||||
dto.ProfileCosmeticId = user.ActiveProfileCosmetic;
|
||||
dto.LastLogin = user.LastLogin;
|
||||
// always add admin tag if user is admin
|
||||
if(user.Role == "Admin")
|
||||
{
|
||||
List<string> _tagList = [.. dto.Tags];
|
||||
_tagList.Add("admin");
|
||||
dto.Tags = [.. _tagList];
|
||||
}
|
||||
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = dto;
|
||||
@ -219,21 +233,24 @@ namespace qtc_api.Services.UserService
|
||||
dbUser.Bio = request.Bio;
|
||||
dbUser.DateOfBirth = request.DateOfBirth;
|
||||
dbUser.ActiveProfileCosmetic = request.ProfileCosmeticId;
|
||||
dbUser.TextStatus = request.TextStatus;
|
||||
|
||||
await _dataContext.SaveChangesAsync();
|
||||
|
||||
var infoDto = new UserInformationDto();
|
||||
|
||||
infoDto.Id = dbUser.Id;
|
||||
infoDto.Username = request.Username;
|
||||
infoDto.ProfilePicture = dbUser.ProfilePicture;
|
||||
infoDto.Bio = request.Bio;
|
||||
infoDto.Role = dbUser.Role;
|
||||
infoDto.DateOfBirth = request.DateOfBirth;
|
||||
infoDto.CreatedAt = dbUser.CreatedAt;
|
||||
infoDto.Status = dbUser.Status;
|
||||
infoDto.CurrencyAmount = dbUser.CurrencyAmount;
|
||||
infoDto.ProfileCosmeticId = request.ProfileCosmeticId;
|
||||
var infoDto = new UserInformationDto
|
||||
{
|
||||
Id = dbUser.Id,
|
||||
Username = request.Username,
|
||||
ProfilePicture = dbUser.ProfilePicture,
|
||||
Bio = request.Bio,
|
||||
Role = dbUser.Role,
|
||||
DateOfBirth = request.DateOfBirth,
|
||||
CreatedAt = dbUser.CreatedAt,
|
||||
Status = dbUser.Status,
|
||||
CurrencyAmount = dbUser.CurrencyAmount,
|
||||
ProfileCosmeticId = request.ProfileCosmeticId,
|
||||
TextStatus = request.TextStatus
|
||||
};
|
||||
|
||||
serviceResponse.Success = true;
|
||||
serviceResponse.Data = infoDto;
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
"S3AccessKey": "",
|
||||
"S3SecretKey": "",
|
||||
"S3ProfileImagesBucket": "qtcnet-profileimages",
|
||||
"S3CDNBucket": "qtcnet-cdn",
|
||||
"S3ImagesBucket": "qtcnet-images"
|
||||
},
|
||||
"Logging": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user