♻️ I have no idea what I have done

This commit is contained in:
2025-07-15 01:54:27 +08:00
parent a03b8d1cac
commit 3c11c4f3be
35 changed files with 1761 additions and 930 deletions

View File

@@ -1,10 +1,13 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Shared;
using DysonNetwork.Shared.Data;
using DysonNetwork.Shared.Proto;
using DysonNetwork.Sphere.Localization;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Sphere.Realm;
using Grpc.Core;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Localization;
using NodaTime;
@@ -20,7 +23,9 @@ public class ChatRoomController(
IStringLocalizer<NotificationResource> localizer,
AccountService.AccountServiceClient accounts,
FileService.FileServiceClient files,
FileReferenceService.FileReferenceServiceClient fileRefs
FileReferenceService.FileReferenceServiceClient fileRefs,
ActionLogService.ActionLogServiceClient als,
PusherService.PusherServiceClient pusher
) : ControllerBase
{
[HttpGet("{id:guid}")]
@@ -123,10 +128,14 @@ public class ChatRoomController(
db.ChatRooms.Add(dmRoom);
await db.SaveChangesAsync();
als.CreateActionLogFromRequest(
ActionLogType.ChatroomCreate,
new Dictionary<string, object> { { "chatroom_id", dmRoom.Id } }, Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = "chatrooms.create",
Meta = { { "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(dmRoom.Id.ToString()) } },
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
var invitedMember = dmRoom.Members.First(m => m.AccountId == request.RelatedUserId);
invitedMember.ChatRoom = dmRoom;
@@ -200,23 +209,44 @@ public class ChatRoomController(
if (request.PictureId is not null)
{
chatRoom.Picture = (await db.Files.FindAsync(request.PictureId))?.ToReferenceObject();
if (chatRoom.Picture is null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
await fileRefs.CreateReferenceAsync(
new CreateReferenceRequest
try
{
var fileResponse = await files.GetFileAsync(new GetFileRequest { Id = request.PictureId });
if (fileResponse == null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
chatRoom.Picture = CloudFileReferenceObject.FromProtoValue(fileResponse);
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
{
FileId = publisher.Picture.Id,
Usage = "publisher.picture",
ResourceId = publisher.ResourceIdentifier,
}
);
FileId = fileResponse.Id,
Usage = "chatroom.picture",
ResourceId = chatRoom.ResourceIdentifier,
});
}
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.NotFound)
{
return BadRequest("Invalid picture id, unable to find the file on cloud.");
}
}
if (request.BackgroundId is not null)
{
chatRoom.Background = (await db.Files.FindAsync(request.BackgroundId))?.ToReferenceObject();
if (chatRoom.Background is null)
try
{
var fileResponse = await files.GetFileAsync(new GetFileRequest { Id = request.BackgroundId });
if (fileResponse == null) return BadRequest("Invalid background id, unable to find the file on cloud.");
chatRoom.Background = CloudFileReferenceObject.FromProtoValue(fileResponse);
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
{
FileId = fileResponse.Id,
Usage = "chatroom.background",
ResourceId = chatRoom.ResourceIdentifier,
});
}
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.NotFound)
{
return BadRequest("Invalid background id, unable to find the file on cloud.");
}
}
db.ChatRooms.Add(chatRoom);
@@ -225,23 +255,33 @@ public class ChatRoomController(
var chatRoomResourceId = $"chatroom:{chatRoom.Id}";
if (chatRoom.Picture is not null)
await fileRefService.CreateReferenceAsync(
chatRoom.Picture.Id,
"chat.room.picture",
chatRoomResourceId
);
{
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
{
FileId = chatRoom.Picture.Id,
Usage = "chat.room.picture",
ResourceId = chatRoomResourceId
});
}
if (chatRoom.Background is not null)
await fileRefService.CreateReferenceAsync(
chatRoom.Background.Id,
"chat.room.background",
chatRoomResourceId
);
{
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
{
FileId = chatRoom.Background.Id,
Usage = "chat.room.background",
ResourceId = chatRoomResourceId
});
}
als.CreateActionLogFromRequest(
ActionLogType.ChatroomCreate,
new Dictionary<string, object> { { "chatroom_id", chatRoom.Id } }, Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = "chatrooms.create",
Meta = { { "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(chatRoom.Id.ToString()) } },
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
return Ok(chatRoom);
}
@@ -279,38 +319,62 @@ public class ChatRoomController(
if (request.PictureId is not null)
{
var picture = await db.Files.FindAsync(request.PictureId);
if (picture is null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
try
{
var fileResponse = await files.GetFileAsync(new GetFileRequest { Id = request.PictureId });
if (fileResponse == null) return BadRequest("Invalid picture id, unable to find the file on cloud.");
// Remove old references for pictures
await fileRefService.DeleteResourceReferencesAsync(chatRoom.ResourceIdentifier, "chat.room.picture");
// Remove old references for pictures
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest
{
ResourceId = chatRoom.ResourceIdentifier,
Usage = "chat.room.picture"
});
// Add a new reference
await fileRefService.CreateReferenceAsync(
picture.Id,
"chat.room.picture",
chatRoom.ResourceIdentifier
);
// Add a new reference
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
{
FileId = fileResponse.Id,
Usage = "chat.room.picture",
ResourceId = chatRoom.ResourceIdentifier
});
chatRoom.Picture = picture.ToReferenceObject();
chatRoom.Picture = CloudFileReferenceObject.FromProtoValue(fileResponse);
}
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.NotFound)
{
return BadRequest("Invalid picture id, unable to find the file on cloud.");
}
}
if (request.BackgroundId is not null)
{
var background = await db.Files.FindAsync(request.BackgroundId);
if (background is null) return BadRequest("Invalid background id, unable to find the file on cloud.");
try
{
var fileResponse = await files.GetFileAsync(new GetFileRequest { Id = request.BackgroundId });
if (fileResponse == null) return BadRequest("Invalid background id, unable to find the file on cloud.");
// Remove old references for backgrounds
await fileRefService.DeleteResourceReferencesAsync(chatRoom.ResourceIdentifier, "chat.room.background");
// Remove old references for backgrounds
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest
{
ResourceId = chatRoom.ResourceIdentifier,
Usage = "chat.room.background"
});
// Add a new reference
await fileRefService.CreateReferenceAsync(
background.Id,
"chat.room.background",
chatRoom.ResourceIdentifier
);
// Add a new reference
await fileRefs.CreateReferenceAsync(new CreateReferenceRequest
{
FileId = fileResponse.Id,
Usage = "chat.room.background",
ResourceId = chatRoom.ResourceIdentifier
});
chatRoom.Background = background.ToReferenceObject();
chatRoom.Background = CloudFileReferenceObject.FromProtoValue(fileResponse);
}
catch (RpcException ex) when (ex.StatusCode == Grpc.Core.StatusCode.NotFound)
{
return BadRequest("Invalid background id, unable to find the file on cloud.");
}
}
if (request.Name is not null)
@@ -325,10 +389,14 @@ public class ChatRoomController(
db.ChatRooms.Update(chatRoom);
await db.SaveChangesAsync();
als.CreateActionLogFromRequest(
ActionLogType.ChatroomUpdate,
new Dictionary<string, object> { { "chatroom_id", chatRoom.Id } }, Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = "chatrooms.update",
Meta = { { "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(chatRoom.Id.ToString()) } },
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
return Ok(chatRoom);
}
@@ -355,15 +423,22 @@ public class ChatRoomController(
var chatRoomResourceId = $"chatroom:{chatRoom.Id}";
// Delete all file references for this chat room
await fileRefService.DeleteResourceReferencesAsync(chatRoomResourceId);
await fileRefs.DeleteResourceReferencesAsync(new DeleteResourceReferencesRequest
{
ResourceId = chatRoomResourceId
});
db.ChatRooms.Remove(chatRoom);
await db.SaveChangesAsync();
als.CreateActionLogFromRequest(
ActionLogType.ChatroomDelete,
new Dictionary<string, object> { { "chatroom_id", chatRoom.Id } }, Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = "chatrooms.delete",
Meta = { { "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(chatRoom.Id.ToString()) } },
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
return NoContent();
}
@@ -411,44 +486,44 @@ public class ChatRoomController(
.Include(m => m.Account)
.Include(m => m.Account.Profile);
if (withStatus)
{
var members = await query
.OrderBy(m => m.JoinedAt)
.ToListAsync();
// if (withStatus)
// {
// var members = await query
// .OrderBy(m => m.JoinedAt)
// .ToListAsync();
//
// var memberStatuses = await aes.GetStatuses(members.Select(m => m.AccountId).ToList());
//
// if (!string.IsNullOrEmpty(status))
// {
// members = members.Where(m =>
// memberStatuses.TryGetValue(m.AccountId, out var s) && s.Label != null &&
// s.Label.Equals(status, StringComparison.OrdinalIgnoreCase)).ToList();
// }
//
// members = members.OrderByDescending(m => memberStatuses.TryGetValue(m.AccountId, out var s) && s.IsOnline)
// .ToList();
//
// var total = members.Count;
// Response.Headers.Append("X-Total", total.ToString());
//
// var result = members.Skip(skip).Take(take).ToList();
//
// return Ok(result);
// }
// else
// {
var total = await query.CountAsync();
Response.Headers.Append("X-Total", total.ToString());
var memberStatuses = await aes.GetStatuses(members.Select(m => m.AccountId).ToList());
var members = await query
.OrderBy(m => m.JoinedAt)
.Skip(skip)
.Take(take)
.ToListAsync();
if (!string.IsNullOrEmpty(status))
{
members = members.Where(m =>
memberStatuses.TryGetValue(m.AccountId, out var s) && s.Label != null &&
s.Label.Equals(status, StringComparison.OrdinalIgnoreCase)).ToList();
}
members = members.OrderByDescending(m => memberStatuses.TryGetValue(m.AccountId, out var s) && s.IsOnline)
.ToList();
var total = members.Count;
Response.Headers.Append("X-Total", total.ToString());
var result = members.Skip(skip).Take(take).ToList();
return Ok(result);
}
else
{
var total = await query.CountAsync();
Response.Headers.Append("X-Total", total.ToString());
var members = await query
.OrderBy(m => m.JoinedAt)
.Skip(skip)
.Take(take)
.ToListAsync();
return Ok(members);
}
return Ok(members);
// }
}
@@ -463,14 +538,23 @@ public class ChatRoomController(
public async Task<ActionResult<ChatMember>> InviteMember(Guid roomId,
[FromBody] ChatMemberRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Shared.Proto.Account currentUser) return Unauthorized();
if (HttpContext.Items["CurrentUser"] is not Account currentUser) return Unauthorized();
var accountId = Guid.Parse(currentUser.Id);
var relatedUser = await db.Accounts.FindAsync(request.RelatedUserId);
if (relatedUser is null) return BadRequest("Related user was not found");
// Get related user account
var relatedUser =
await accounts.GetAccountAsync(new GetAccountRequest { Id = request.RelatedUserId.ToString() });
if (relatedUser == null) return BadRequest("Related user was not found");
if (await rels.HasRelationshipWithStatus(Guid.Parse(currentUser.Id), relatedUser.Id,
RelationshipStatus.Blocked))
// Check if the user has blocked the current user
var relationship = await accounts.GetRelationshipAsync(new GetRelationshipRequest
{
AccountId = currentUser.Id,
RelatedId = relatedUser.Id,
Status = -100
});
if (relationship != null && relationship.Relationship.Status == -100)
return StatusCode(403, "You cannot invite a user that blocked you.");
var chatRoom = await db.ChatRooms
@@ -512,7 +596,7 @@ public class ChatRoomController(
var newMember = new ChatMember
{
AccountId = relatedUser.Id,
AccountId = Guid.Parse(relatedUser.Id),
ChatRoomId = roomId,
Role = request.Role,
};
@@ -523,10 +607,18 @@ public class ChatRoomController(
newMember.ChatRoom = chatRoom;
await _SendInviteNotify(newMember, currentUser);
als.CreateActionLogFromRequest(
ActionLogType.ChatroomInvite,
new Dictionary<string, object> { { "chatroom_id", chatRoom.Id }, { "account_id", relatedUser.Id } }, Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = "chatrooms.invite",
Meta =
{
{ "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(chatRoom.Id.ToString()) },
{ "account_id", Google.Protobuf.WellKnownTypes.Value.ForString(relatedUser.Id.ToString()) }
},
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
return Ok(newMember);
}
@@ -575,10 +667,14 @@ public class ChatRoomController(
await db.SaveChangesAsync();
_ = crs.PurgeRoomMembersCache(roomId);
als.CreateActionLogFromRequest(
ActionLogType.ChatroomJoin,
new Dictionary<string, object> { { "chatroom_id", roomId } }, Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = ActionLogType.ChatroomJoin,
Meta = { { "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(roomId.ToString()) } },
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
return Ok(member);
}
@@ -688,12 +784,19 @@ public class ChatRoomController(
await crs.PurgeRoomMembersCache(roomId);
als.CreateActionLogFromRequest(
ActionLogType.RealmAdjustRole,
new Dictionary<string, object>
{ { "chatroom_id", roomId }, { "account_id", memberId }, { "new_role", newRole } },
Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = "chatrooms.role.edit",
Meta =
{
{ "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(roomId.ToString()) },
{ "account_id", Google.Protobuf.WellKnownTypes.Value.ForString(memberId.ToString()) },
{ "new_role", Google.Protobuf.WellKnownTypes.Value.ForNumber(newRole) }
},
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
return Ok(targetMember);
}
@@ -738,10 +841,18 @@ public class ChatRoomController(
await db.SaveChangesAsync();
_ = crs.PurgeRoomMembersCache(roomId);
als.CreateActionLogFromRequest(
ActionLogType.ChatroomKick,
new Dictionary<string, object> { { "chatroom_id", roomId }, { "account_id", memberId } }, Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = "chatrooms.kick",
Meta =
{
{ "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(roomId.ToString()) },
{ "account_id", Google.Protobuf.WellKnownTypes.Value.ForString(memberId.ToString()) }
},
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
return NoContent();
}
@@ -780,10 +891,14 @@ public class ChatRoomController(
await db.SaveChangesAsync();
_ = crs.PurgeRoomMembersCache(roomId);
als.CreateActionLogFromRequest(
ActionLogType.ChatroomJoin,
new Dictionary<string, object> { { "chatroom_id", roomId } }, Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = ActionLogType.ChatroomJoin,
Meta = { { "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(roomId.ToString()) } },
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
return Ok(chatRoom);
}
@@ -817,10 +932,14 @@ public class ChatRoomController(
await db.SaveChangesAsync();
await crs.PurgeRoomMembersCache(roomId);
als.CreateActionLogFromRequest(
ActionLogType.ChatroomLeave,
new Dictionary<string, object> { { "chatroom_id", roomId } }, Request
);
_ = als.CreateActionLogAsync(new CreateActionLogRequest
{
Action = ActionLogType.ChatroomLeave,
Meta = { { "chatroom_id", Google.Protobuf.WellKnownTypes.Value.ForString(roomId.ToString()) } },
AccountId = currentUser.Id,
UserAgent = Request.Headers.UserAgent,
IpAddress = Request.HttpContext.Connection.RemoteIpAddress?.ToString()
});
return NoContent();
}
@@ -833,7 +952,19 @@ public class ChatRoomController(
? localizer["ChatInviteDirectBody", sender.Nick]
: localizer["ChatInviteBody", member.ChatRoom.Name ?? "Unnamed"];
AccountService.SetCultureInfo(member.Account);
await nty.SendNotification(member.Account, "invites.chats", title, null, body, actionUri: "/chat");
CultureService.SetCultureInfo(member.Account);
await pusher.SendPushNotificationToUserAsync(
new SendPushNotificationToUserRequest
{
UserId = member.Account.Id.ToString(),
Notification = new PushNotification
{
Topic = "invites.chats",
Title = title,
Body = body,
IsSavable = false
}
}
);
}
}