🐛 Fixes in CloudFile filemeta transfer via gRPC
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using DysonNetwork.Shared.Data;
|
||||
using DysonNetwork.Shared.Proto;
|
||||
using Google.Protobuf;
|
||||
using Newtonsoft.Json;
|
||||
using NodaTime;
|
||||
using NodaTime.Serialization.Protobuf;
|
||||
|
||||
@@ -103,7 +106,7 @@ public class CloudFile : ModelBase, ICloudFile, IIdentifiedResource
|
||||
/// <returns>The protobuf message representation of this object</returns>
|
||||
public Shared.Proto.CloudFile ToProtoValue()
|
||||
{
|
||||
var protoFile = new Shared.Proto.CloudFile
|
||||
var proto = new Shared.Proto.CloudFile
|
||||
{
|
||||
Id = Id,
|
||||
Name = Name ?? string.Empty,
|
||||
@@ -113,28 +116,18 @@ public class CloudFile : ModelBase, ICloudFile, IIdentifiedResource
|
||||
HasCompression = HasCompression,
|
||||
Url = StorageUrl ?? string.Empty,
|
||||
ContentType = MimeType ?? string.Empty,
|
||||
UploadedAt = UploadedAt?.ToTimestamp()
|
||||
UploadedAt = UploadedAt?.ToTimestamp(),
|
||||
// Convert file metadata
|
||||
FileMeta = ByteString.CopyFromUtf8(
|
||||
System.Text.Json.JsonSerializer.Serialize(FileMeta, GrpcTypeHelper.SystemTextSerializerOptions)
|
||||
),
|
||||
// Convert user metadata
|
||||
UserMeta = ByteString.CopyFromUtf8(
|
||||
System.Text.Json.JsonSerializer.Serialize(UserMeta, GrpcTypeHelper.SystemTextSerializerOptions)
|
||||
)
|
||||
};
|
||||
|
||||
// Convert FileMeta dictionary
|
||||
if (FileMeta != null)
|
||||
{
|
||||
foreach (var (key, value) in FileMeta)
|
||||
{
|
||||
protoFile.FileMeta[key] = Google.Protobuf.WellKnownTypes.Value.ForString(value?.ToString() ?? string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert UserMeta dictionary
|
||||
if (UserMeta != null)
|
||||
{
|
||||
foreach (var (key, value) in UserMeta)
|
||||
{
|
||||
protoFile.UserMeta[key] = Google.Protobuf.WellKnownTypes.Value.ForString(value?.ToString() ?? string.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
return protoFile;
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
using DysonNetwork.Shared.Proto;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Google.Protobuf;
|
||||
|
||||
namespace DysonNetwork.Shared.Data;
|
||||
|
||||
@@ -41,10 +41,14 @@ public class CloudFileReferenceObject : ModelBase, ICloudFile
|
||||
{
|
||||
Id = proto.Id,
|
||||
Name = proto.Name,
|
||||
FileMeta = proto.FileMeta
|
||||
.ToDictionary(kvp => kvp.Key, kvp => GrpcTypeHelper.ConvertValueToObject(kvp.Value)),
|
||||
UserMeta = proto.UserMeta
|
||||
.ToDictionary(kvp => kvp.Key, kvp => GrpcTypeHelper.ConvertValueToObject(kvp.Value)),
|
||||
FileMeta = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object?>>(
|
||||
proto.FileMeta.ToStringUtf8(),
|
||||
GrpcTypeHelper.SystemTextSerializerOptions
|
||||
) ?? [],
|
||||
UserMeta = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object?>>(
|
||||
proto.UserMeta.ToStringUtf8(),
|
||||
GrpcTypeHelper.SystemTextSerializerOptions
|
||||
) ?? [],
|
||||
MimeType = proto.MimeType,
|
||||
Hash = proto.Hash,
|
||||
Size = proto.Size,
|
||||
@@ -55,9 +59,9 @@ public class CloudFileReferenceObject : ModelBase, ICloudFile
|
||||
/// <summary>
|
||||
/// Converts the current object to its protobuf representation
|
||||
/// </summary>
|
||||
public Proto.CloudFile ToProtoValue()
|
||||
public CloudFile ToProtoValue()
|
||||
{
|
||||
var proto = new Proto.CloudFile
|
||||
var proto = new CloudFile
|
||||
{
|
||||
Id = Id,
|
||||
Name = Name,
|
||||
@@ -70,22 +74,14 @@ public class CloudFileReferenceObject : ModelBase, ICloudFile
|
||||
};
|
||||
|
||||
// Convert file metadata
|
||||
if (FileMeta != null)
|
||||
{
|
||||
foreach (var (key, value) in FileMeta)
|
||||
{
|
||||
proto.FileMeta[key] = Value.ForString(value?.ToString() ?? string.Empty);
|
||||
}
|
||||
}
|
||||
proto.FileMeta = ByteString.CopyFromUtf8(
|
||||
System.Text.Json.JsonSerializer.Serialize(FileMeta, GrpcTypeHelper.SystemTextSerializerOptions)
|
||||
);
|
||||
|
||||
// Convert user metadata
|
||||
if (UserMeta != null)
|
||||
{
|
||||
foreach (var (key, value) in UserMeta)
|
||||
{
|
||||
proto.UserMeta[key] = Value.ForString(value?.ToString() ?? string.Empty);
|
||||
}
|
||||
}
|
||||
proto.UserMeta = ByteString.CopyFromUtf8(
|
||||
System.Text.Json.JsonSerializer.Serialize(UserMeta, GrpcTypeHelper.SystemTextSerializerOptions)
|
||||
);
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Google.Protobuf.Collections;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Newtonsoft.Json;
|
||||
@@ -8,7 +9,14 @@ namespace DysonNetwork.Shared.Proto;
|
||||
|
||||
public abstract class GrpcTypeHelper
|
||||
{
|
||||
private static readonly JsonSerializerSettings SerializerSettings = new()
|
||||
public static readonly JsonSerializerOptions SystemTextSerializerOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
Converters = { new JsonStringEnumConverter() }
|
||||
};
|
||||
|
||||
public static readonly JsonSerializerSettings SerializerSettings = new()
|
||||
{
|
||||
ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() },
|
||||
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
|
||||
|
@@ -19,11 +19,11 @@ message CloudFile {
|
||||
// Original name of the file
|
||||
string name = 2;
|
||||
|
||||
// The metadata uses JSON bytes to store to keep the data structure over gRPC
|
||||
// File metadata (e.g., dimensions, duration, etc.)
|
||||
map<string, google.protobuf.Value> file_meta = 3;
|
||||
|
||||
bytes file_meta = 3;
|
||||
// User-defined metadata
|
||||
map<string, google.protobuf.Value> user_meta = 4;
|
||||
bytes user_meta = 4;
|
||||
|
||||
// MIME type of the file
|
||||
string mime_type = 5;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
using DysonNetwork.Pass.Account;
|
||||
using DysonNetwork.Shared.Data;
|
||||
using DysonNetwork.Sphere.Chat;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -48,6 +49,7 @@ public class RealmMember : ModelBase
|
||||
public Guid RealmId { get; set; }
|
||||
public Realm Realm { get; set; } = null!;
|
||||
public Guid AccountId { get; set; }
|
||||
[NotMapped] public Account? Account { get; set; }
|
||||
|
||||
public int Role { get; set; } = RealmMemberRole.Normal;
|
||||
public Instant? JoinedAt { get; set; }
|
||||
|
@@ -62,7 +62,7 @@ public class RealmController(
|
||||
.Include(e => e.Realm)
|
||||
.ToListAsync();
|
||||
|
||||
return members.ToList();
|
||||
return await rs.LoadMemberAccounts(members);
|
||||
}
|
||||
|
||||
public class RealmMemberRequest
|
||||
@@ -256,7 +256,7 @@ public class RealmController(
|
||||
//
|
||||
// var result = members.Skip(offset).Take(take).ToList();
|
||||
//
|
||||
// return Ok(result);
|
||||
// return Ok(await rs.LoadMemberAccounts(result));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
@@ -269,7 +269,7 @@ public class RealmController(
|
||||
.Take(take)
|
||||
.ToListAsync();
|
||||
|
||||
return Ok(members);
|
||||
return Ok(await rs.LoadMemberAccounts(members));
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@ public class RealmController(
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (member is null) return NotFound();
|
||||
return Ok(member);
|
||||
return Ok(await rs.LoadMemberAccount(member));
|
||||
}
|
||||
|
||||
[HttpDelete("{slug}/members/me")]
|
||||
|
@@ -1,5 +1,6 @@
|
||||
using DysonNetwork.Shared;
|
||||
using DysonNetwork.Shared.Proto;
|
||||
using DysonNetwork.Shared.Registry;
|
||||
using DysonNetwork.Sphere.Localization;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Localization;
|
||||
@@ -10,7 +11,8 @@ public class RealmService(
|
||||
AppDatabase db,
|
||||
PusherService.PusherServiceClient pusher,
|
||||
AccountService.AccountServiceClient accounts,
|
||||
IStringLocalizer<NotificationResource> localizer
|
||||
IStringLocalizer<NotificationResource> localizer,
|
||||
AccountClientHelper accountsHelper
|
||||
)
|
||||
{
|
||||
public async Task SendInviteNotify(RealmMember member)
|
||||
@@ -44,4 +46,24 @@ public class RealmService(
|
||||
.FirstOrDefaultAsync(m => m.RealmId == realmId && m.AccountId == accountId);
|
||||
return member?.Role >= maxRequiredRole;
|
||||
}
|
||||
|
||||
public async Task<RealmMember> LoadMemberAccount(RealmMember member)
|
||||
{
|
||||
var account = await accountsHelper.GetAccount(member.AccountId);
|
||||
member.Account = Pass.Account.Account.FromProtoValue(account);
|
||||
return member;
|
||||
}
|
||||
|
||||
public async Task<List<RealmMember>> LoadMemberAccounts(ICollection<RealmMember> members)
|
||||
{
|
||||
var accountIds = members.Select(m => m.AccountId).ToList();
|
||||
var accounts = (await accountsHelper.GetAccountBatch(accountIds)).ToDictionary(a => Guid.Parse(a.Id), a => a);
|
||||
|
||||
return members.Select(m =>
|
||||
{
|
||||
if (accounts.TryGetValue(m.AccountId, out var account))
|
||||
m.Account = Pass.Account.Account.FromProtoValue(account);
|
||||
return m;
|
||||
}).ToList();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user