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