Compare commits
No commits in common. "30db6ad9f17a6a422512647808ca425c75c2c344" and "b1543f5b0898a605371feba9da8318686ffa95c7" have entirely different histories.
30db6ad9f1
...
b1543f5b08
@ -1,5 +1,4 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Activity;
|
namespace DysonNetwork.Sphere.Activity;
|
||||||
|
|
||||||
@ -7,7 +6,6 @@ public enum ActivityVisibility
|
|||||||
{
|
{
|
||||||
Public,
|
Public,
|
||||||
Friends,
|
Friends,
|
||||||
Selected
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Activity : ModelBase
|
public class Activity : ModelBase
|
||||||
@ -16,11 +14,8 @@ public class Activity : ModelBase
|
|||||||
[MaxLength(1024)] public string Type { get; set; } = null!;
|
[MaxLength(1024)] public string Type { get; set; } = null!;
|
||||||
[MaxLength(4096)] public string ResourceIdentifier { get; set; } = null!;
|
[MaxLength(4096)] public string ResourceIdentifier { get; set; } = null!;
|
||||||
public ActivityVisibility Visibility { get; set; } = ActivityVisibility.Public;
|
public ActivityVisibility Visibility { get; set; } = ActivityVisibility.Public;
|
||||||
[Column(TypeName = "jsonb")] public Dictionary<string, object> Meta = new();
|
public Dictionary<string, object> Meta = new();
|
||||||
[Column(TypeName = "jsonb")] public ICollection<long> UsersVisible = new List<long>();
|
|
||||||
|
|
||||||
public long AccountId { get; set; }
|
public long AccountId { get; set; }
|
||||||
public Account.Account Account { get; set; } = null!;
|
public Account.Account Account { get; set; } = null!;
|
||||||
|
|
||||||
[NotMapped] public object? Data { get; set; }
|
|
||||||
}
|
}
|
@ -13,22 +13,21 @@ public class ActivityController(AppDatabase db, ActivityService act, Relationshi
|
|||||||
{
|
{
|
||||||
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
|
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
|
||||||
var currentUser = currentUserValue as Account.Account;
|
var currentUser = currentUserValue as Account.Account;
|
||||||
var userFriends = currentUser is null ? null : await rels.ListAccountFriends(currentUser);
|
var userFriends = await rels.ListAccountFriends(currentUser!);
|
||||||
|
|
||||||
var totalCount = await db.Activities
|
var totalCount = await db.Activities
|
||||||
.FilterWithVisibility(currentUser, userFriends)
|
.FilterWithVisibility(currentUser, userFriends)
|
||||||
.CountAsync();
|
.CountAsync();
|
||||||
var activities = await db.Activities
|
var posts = await db.Activities
|
||||||
.Include(e => e.Account)
|
.Include(e => e.Account)
|
||||||
.FilterWithVisibility(currentUser, userFriends)
|
.FilterWithVisibility(currentUser, userFriends)
|
||||||
.OrderByDescending(e => e.CreatedAt)
|
.OrderByDescending(e => e.CreatedAt)
|
||||||
.Skip(offset)
|
.Skip(offset)
|
||||||
.Take(take)
|
.Take(take)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
activities = await act.LoadActivityData(activities, currentUser, userFriends);
|
|
||||||
|
|
||||||
Response.Headers["X-Total"] = totalCount.ToString();
|
Response.Headers["X-Total"] = totalCount.ToString();
|
||||||
|
|
||||||
return Ok(activities);
|
return Ok(posts);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,60 +1,15 @@
|
|||||||
using DysonNetwork.Sphere.Post;
|
using DysonNetwork.Sphere.Post;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Activity;
|
namespace DysonNetwork.Sphere.Activity;
|
||||||
|
|
||||||
public class ActivityService(AppDatabase db)
|
public class ActivityService(AppDatabase db)
|
||||||
{
|
{
|
||||||
public async Task<List<Activity>> LoadActivityData(List<Activity> input, Account.Account? currentUser,
|
|
||||||
List<long> userFriends)
|
|
||||||
{
|
|
||||||
if (input.Count == 0) return input;
|
|
||||||
|
|
||||||
var postsId = input
|
|
||||||
.Where(e => e.ResourceIdentifier.StartsWith("posts/"))
|
|
||||||
.Select(e => long.Parse(e.ResourceIdentifier.Split("/").Last()))
|
|
||||||
.Distinct()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
if (postsId.Count > 0)
|
|
||||||
{
|
|
||||||
var posts = await db.Posts.Where(e => postsId.Contains(e.Id))
|
|
||||||
.Include(e => e.Publisher)
|
|
||||||
.Include(e => e.Publisher.Picture)
|
|
||||||
.Include(e => e.Publisher.Background)
|
|
||||||
.Include(e => e.ThreadedPost)
|
|
||||||
.Include(e => e.ForwardedPost)
|
|
||||||
.Include(e => e.Attachments)
|
|
||||||
.Include(e => e.Categories)
|
|
||||||
.Include(e => e.Tags)
|
|
||||||
.FilterWithVisibility(currentUser, userFriends)
|
|
||||||
.ToListAsync();
|
|
||||||
posts = PostService.TruncatePostContent(posts);
|
|
||||||
|
|
||||||
var postsDict = posts.ToDictionary(p => p.Id);
|
|
||||||
|
|
||||||
for (var idx = 0; idx < input.Count; idx++)
|
|
||||||
{
|
|
||||||
var resourceIdentifier = input[idx].ResourceIdentifier;
|
|
||||||
if (!resourceIdentifier.StartsWith("posts/")) continue;
|
|
||||||
var postId = long.Parse(resourceIdentifier.Split("/").Last());
|
|
||||||
if (postsDict.TryGetValue(postId, out var post) && input[idx].Data is null)
|
|
||||||
{
|
|
||||||
input[idx].Data = post;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Activity> CreateActivity(
|
public async Task<Activity> CreateActivity(
|
||||||
Account.Account user,
|
Account.Account user,
|
||||||
string type,
|
string type,
|
||||||
string identifier,
|
string identifier,
|
||||||
ActivityVisibility visibility = ActivityVisibility.Public,
|
ActivityVisibility visibility = ActivityVisibility.Public
|
||||||
List<long>? visibleUsers = null
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var activity = new Activity
|
var activity = new Activity
|
||||||
@ -63,7 +18,6 @@ public class ActivityService(AppDatabase db)
|
|||||||
ResourceIdentifier = identifier,
|
ResourceIdentifier = identifier,
|
||||||
Visibility = visibility,
|
Visibility = visibility,
|
||||||
AccountId = user.Id,
|
AccountId = user.Id,
|
||||||
UsersVisible = visibleUsers ?? []
|
|
||||||
};
|
};
|
||||||
|
|
||||||
db.Activities.Add(activity);
|
db.Activities.Add(activity);
|
||||||
@ -77,26 +31,8 @@ public class ActivityService(AppDatabase db)
|
|||||||
if (post.Visibility is PostVisibility.Unlisted or PostVisibility.Private) return;
|
if (post.Visibility is PostVisibility.Unlisted or PostVisibility.Private) return;
|
||||||
|
|
||||||
var identifier = $"posts/{post.Id}";
|
var identifier = $"posts/{post.Id}";
|
||||||
if (post.RepliedPostId is not null)
|
await CreateActivity(user, "posts.new", identifier,
|
||||||
{
|
post.Visibility == PostVisibility.Friends ? ActivityVisibility.Friends : ActivityVisibility.Public);
|
||||||
var ogPost = await db.Posts.Where(e => e.Id == post.RepliedPostId).Include(e => e.Publisher)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
if (ogPost == null) return;
|
|
||||||
await CreateActivity(
|
|
||||||
user,
|
|
||||||
"posts.new.replies",
|
|
||||||
identifier,
|
|
||||||
ActivityVisibility.Selected,
|
|
||||||
[ogPost.Publisher.AccountId!.Value]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await CreateActivity(
|
|
||||||
user,
|
|
||||||
"posts.new",
|
|
||||||
identifier,
|
|
||||||
post.Visibility == PostVisibility.Friends ? ActivityVisibility.Friends : ActivityVisibility.Public
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,13 +41,14 @@ public static class ActivityQueryExtensions
|
|||||||
public static IQueryable<Activity> FilterWithVisibility(this IQueryable<Activity> source,
|
public static IQueryable<Activity> FilterWithVisibility(this IQueryable<Activity> source,
|
||||||
Account.Account? currentUser, List<long> userFriends)
|
Account.Account? currentUser, List<long> userFriends)
|
||||||
{
|
{
|
||||||
|
var now = Instant.FromDateTimeUtc(DateTime.UtcNow);
|
||||||
|
|
||||||
if (currentUser is null)
|
if (currentUser is null)
|
||||||
return source.Where(e => e.Visibility == ActivityVisibility.Public);
|
return source.Where(e => e.Visibility == ActivityVisibility.Public);
|
||||||
|
|
||||||
return source
|
return source
|
||||||
.Where(e => e.Visibility != ActivityVisibility.Friends ||
|
.Where(e => e.Visibility != ActivityVisibility.Friends ||
|
||||||
userFriends.Contains(e.AccountId) ||
|
userFriends.Contains(e.AccountId) ||
|
||||||
e.AccountId == currentUser.Id)
|
e.AccountId == currentUser.Id);
|
||||||
.Where(e => e.Visibility != ActivityVisibility.Selected || e.UsersVisible.Contains(currentUser.Id));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -20,11 +20,11 @@ public class AppDatabase(
|
|||||||
IConfiguration configuration
|
IConfiguration configuration
|
||||||
) : DbContext(options)
|
) : DbContext(options)
|
||||||
{
|
{
|
||||||
public DbSet<PermissionNode> PermissionNodes { get; set; }
|
public DbSet<PermissionNode> PermissionNodes { get; set; } = null!;
|
||||||
public DbSet<PermissionGroup> PermissionGroups { get; set; }
|
public DbSet<PermissionGroup> PermissionGroups { get; set; } = null!;
|
||||||
public DbSet<PermissionGroupMember> PermissionGroupMembers { get; set; }
|
public DbSet<PermissionGroupMember> PermissionGroupMembers { get; set; } = null!;
|
||||||
|
|
||||||
public DbSet<Account.MagicSpell> MagicSpells { get; set; }
|
public DbSet<Account.MagicSpell> MagicSpells { get; set; } = null!;
|
||||||
public DbSet<Account.Account> Accounts { get; set; }
|
public DbSet<Account.Account> Accounts { get; set; }
|
||||||
public DbSet<Account.Profile> AccountProfiles { get; set; }
|
public DbSet<Account.Profile> AccountProfiles { get; set; }
|
||||||
public DbSet<Account.AccountContact> AccountContacts { get; set; }
|
public DbSet<Account.AccountContact> AccountContacts { get; set; }
|
||||||
@ -48,9 +48,6 @@ public class AppDatabase(
|
|||||||
public DbSet<Post.PostCategory> PostCategories { get; set; }
|
public DbSet<Post.PostCategory> PostCategories { get; set; }
|
||||||
public DbSet<Post.PostCollection> PostCollections { get; set; }
|
public DbSet<Post.PostCollection> PostCollections { get; set; }
|
||||||
|
|
||||||
public DbSet<Realm.Realm> Realms { get; set; }
|
|
||||||
public DbSet<Realm.RealmMember> RealmMembers { get; set; }
|
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
var dataSourceBuilder = new NpgsqlDataSourceBuilder(configuration.GetConnectionString("App"));
|
var dataSourceBuilder = new NpgsqlDataSourceBuilder(configuration.GetConnectionString("App"));
|
||||||
@ -157,30 +154,19 @@ public class AppDatabase(
|
|||||||
.HasMany(p => p.Collections)
|
.HasMany(p => p.Collections)
|
||||||
.WithMany(c => c.Posts)
|
.WithMany(c => c.Posts)
|
||||||
.UsingEntity(j => j.ToTable("post_collection_links"));
|
.UsingEntity(j => j.ToTable("post_collection_links"));
|
||||||
|
|
||||||
modelBuilder.Entity<Realm.RealmMember>()
|
|
||||||
.HasKey(pm => new { pm.RealmId, pm.AccountId });
|
|
||||||
modelBuilder.Entity<Realm.RealmMember>()
|
|
||||||
.HasOne(pm => pm.Realm)
|
|
||||||
.WithMany(p => p.Members)
|
|
||||||
.HasForeignKey(pm => pm.RealmId)
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
modelBuilder.Entity<Post.PublisherMember>()
|
|
||||||
.HasOne(pm => pm.Account)
|
|
||||||
.WithMany()
|
|
||||||
.HasForeignKey(pm => pm.AccountId)
|
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
|
||||||
|
|
||||||
// Automatically apply soft-delete filter to all entities inheriting BaseModel
|
// Automatically apply soft-delete filter to all entities inheriting BaseModel
|
||||||
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
|
||||||
{
|
{
|
||||||
if (!typeof(ModelBase).IsAssignableFrom(entityType.ClrType)) continue;
|
if (typeof(ModelBase).IsAssignableFrom(entityType.ClrType))
|
||||||
var method = typeof(AppDatabase)
|
{
|
||||||
.GetMethod(nameof(SetSoftDeleteFilter),
|
var method = typeof(AppDatabase)
|
||||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)!
|
.GetMethod(nameof(SetSoftDeleteFilter),
|
||||||
.MakeGenericMethod(entityType.ClrType);
|
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)!
|
||||||
|
.MakeGenericMethod(entityType.ClrType);
|
||||||
|
|
||||||
method.Invoke(null, [modelBuilder]);
|
method.Invoke(null, [modelBuilder]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public class PermissionService(AppDatabase db)
|
|||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
var permission = await db.PermissionNodes
|
var permission = await db.PermissionNodes
|
||||||
.Where(n => n.GroupId == null || groupsId.Contains(n.GroupId.Value))
|
.Where(n => n.GroupId == null || groupsId.Contains(n.GroupId.Value))
|
||||||
.Where(n => (n.Key == key || n.Key == "*") && (n.GroupId != null || n.Actor == actor) && n.Area == area)
|
.Where(n => n.Key == key && (n.GroupId != null || n.Actor == actor) && n.Area == area)
|
||||||
.Where(n => n.ExpiredAt == null || n.ExpiredAt < now)
|
.Where(n => n.ExpiredAt == null || n.ExpiredAt < now)
|
||||||
.Where(n => n.AffectedAt == null || n.AffectedAt >= now)
|
.Where(n => n.AffectedAt == null || n.AffectedAt >= now)
|
||||||
.FirstOrDefaultAsync();
|
.FirstOrDefaultAsync();
|
||||||
|
@ -51,7 +51,7 @@ public class Post : ModelBase
|
|||||||
public Post? ForwardedPost { get; set; }
|
public Post? ForwardedPost { get; set; }
|
||||||
public ICollection<CloudFile> Attachments { get; set; } = new List<CloudFile>();
|
public ICollection<CloudFile> Attachments { get; set; } = new List<CloudFile>();
|
||||||
|
|
||||||
[JsonIgnore] public NpgsqlTsVector SearchVector { get; set; }
|
public NpgsqlTsVector SearchVector { get; set; }
|
||||||
|
|
||||||
public Publisher Publisher { get; set; } = null!;
|
public Publisher Publisher { get; set; } = null!;
|
||||||
public ICollection<PostReaction> Reactions { get; set; } = new List<PostReaction>();
|
public ICollection<PostReaction> Reactions { get; set; } = new List<PostReaction>();
|
||||||
@ -59,8 +59,7 @@ public class Post : ModelBase
|
|||||||
public ICollection<PostCategory> Categories { get; set; } = new List<PostCategory>();
|
public ICollection<PostCategory> Categories { get; set; } = new List<PostCategory>();
|
||||||
public ICollection<PostCollection> Collections { get; set; } = new List<PostCollection>();
|
public ICollection<PostCollection> Collections { get; set; } = new List<PostCollection>();
|
||||||
|
|
||||||
[JsonIgnore] public bool Empty => Content == null && Attachments.Count == 0 && ForwardedPostId == null;
|
public bool Empty => Content == null && Attachments.Count == 0 && ForwardedPostId == null;
|
||||||
[NotMapped] public bool IsTruncated = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PostTag : ModelBase
|
public class PostTag : ModelBase
|
||||||
|
@ -38,7 +38,6 @@ public class PostController(AppDatabase db, PostService ps, RelationshipService
|
|||||||
.Skip(offset)
|
.Skip(offset)
|
||||||
.Take(take)
|
.Take(take)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
posts = PostService.TruncatePostContent(posts);
|
|
||||||
|
|
||||||
Response.Headers["X-Total"] = totalCount.ToString();
|
Response.Headers["X-Total"] = totalCount.ToString();
|
||||||
|
|
||||||
@ -102,7 +101,6 @@ public class PostController(AppDatabase db, PostService ps, RelationshipService
|
|||||||
.Skip(offset)
|
.Skip(offset)
|
||||||
.Take(take)
|
.Take(take)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
posts = PostService.TruncatePostContent(posts);
|
|
||||||
|
|
||||||
Response.Headers["X-Total"] = totalCount.ToString();
|
Response.Headers["X-Total"] = totalCount.ToString();
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
using System.Text.Json;
|
|
||||||
using DysonNetwork.Sphere.Activity;
|
using DysonNetwork.Sphere.Activity;
|
||||||
using DysonNetwork.Sphere.Storage;
|
using DysonNetwork.Sphere.Storage;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -8,64 +7,6 @@ namespace DysonNetwork.Sphere.Post;
|
|||||||
|
|
||||||
public class PostService(AppDatabase db, FileService fs, ActivityService act)
|
public class PostService(AppDatabase db, FileService fs, ActivityService act)
|
||||||
{
|
{
|
||||||
public static List<Post> TruncatePostContent(List<Post> input)
|
|
||||||
{
|
|
||||||
// This truncate post content is designed for quill delta
|
|
||||||
const int maxLength = 256;
|
|
||||||
foreach (var item in input)
|
|
||||||
{
|
|
||||||
if (item.Content is not { RootElement: var rootElement }) continue;
|
|
||||||
|
|
||||||
if (rootElement.ValueKind != JsonValueKind.Array) continue;
|
|
||||||
var totalLength = 0;
|
|
||||||
var truncatedArrayElements = new List<JsonElement>();
|
|
||||||
|
|
||||||
foreach (var element in rootElement.EnumerateArray())
|
|
||||||
{
|
|
||||||
if (element is { ValueKind: JsonValueKind.Object } &&
|
|
||||||
element.TryGetProperty("insert", out var insertProperty))
|
|
||||||
{
|
|
||||||
if (insertProperty is { ValueKind: JsonValueKind.String })
|
|
||||||
{
|
|
||||||
var textContent = insertProperty.GetString()!;
|
|
||||||
if (totalLength + textContent.Length <= maxLength)
|
|
||||||
{
|
|
||||||
truncatedArrayElements.Add(element);
|
|
||||||
totalLength += textContent.Length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var remainingLength = maxLength - totalLength;
|
|
||||||
if (remainingLength > 0)
|
|
||||||
{
|
|
||||||
using var truncatedElementDocument =
|
|
||||||
JsonDocument.Parse(
|
|
||||||
$@"{{ ""insert"": ""{textContent.Substring(0, remainingLength)}"" }}"
|
|
||||||
);
|
|
||||||
truncatedArrayElements.Add(truncatedElementDocument.RootElement.Clone());
|
|
||||||
totalLength = maxLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
truncatedArrayElements.Add(element);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
truncatedArrayElements.Add(element);
|
|
||||||
|
|
||||||
if (totalLength >= maxLength)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
using var newDocument = JsonDocument.Parse(JsonSerializer.Serialize(truncatedArrayElements));
|
|
||||||
item.Content = newDocument;
|
|
||||||
}
|
|
||||||
|
|
||||||
return input;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<Post> PostAsync(
|
public async Task<Post> PostAsync(
|
||||||
Account.Account user,
|
Account.Account user,
|
||||||
Post post,
|
Post post,
|
||||||
|
@ -41,7 +41,7 @@ public enum PublisherMemberRole
|
|||||||
Viewer = 25
|
Viewer = 25
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PublisherMember
|
public class PublisherMember : ModelBase
|
||||||
{
|
{
|
||||||
public long PublisherId { get; set; }
|
public long PublisherId { get; set; }
|
||||||
[JsonIgnore] public Publisher Publisher { get; set; } = null!;
|
[JsonIgnore] public Publisher Publisher { get; set; } = null!;
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
using DysonNetwork.Sphere.Storage;
|
|
||||||
using NodaTime;
|
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Realm;
|
|
||||||
|
|
||||||
public class Realm : ModelBase
|
|
||||||
{
|
|
||||||
public long Id { get; set; }
|
|
||||||
[MaxLength(1024)] public string Name { get; set; } = string.Empty;
|
|
||||||
[MaxLength(4096)] public string Description { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
public CloudFile? Picture { get; set; }
|
|
||||||
public CloudFile? Background { get; set; }
|
|
||||||
|
|
||||||
[JsonIgnore] public ICollection<RealmMember> Members { get; set; } = new List<RealmMember>();
|
|
||||||
|
|
||||||
public long AccountId { get; set; }
|
|
||||||
[JsonIgnore] public Account.Account Account { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum RealmMemberRole
|
|
||||||
{
|
|
||||||
Owner = 100,
|
|
||||||
Moderator = 50,
|
|
||||||
Normal = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RealmMember : ModelBase
|
|
||||||
{
|
|
||||||
public long RealmId { get; set; }
|
|
||||||
[JsonIgnore] public Realm Realm { get; set; } = null!;
|
|
||||||
public long AccountId { get; set; }
|
|
||||||
[JsonIgnore] public Account.Account Account { get; set; } = null!;
|
|
||||||
|
|
||||||
public RealmMemberRole Role { get; set; }
|
|
||||||
public Instant? JoinedAt { get; set; }
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Realm;
|
|
||||||
|
|
||||||
[ApiController]
|
|
||||||
[Route("/realms")]
|
|
||||||
public class RealmController : ControllerBase
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
namespace DysonNetwork.Sphere.Realm;
|
|
||||||
|
|
||||||
public class RealmService(AppDatabase db)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user