:drunk: Write shit code trying to split up the Auth (WIP)

This commit is contained in:
2025-07-06 12:58:18 +08:00
parent 5757526ea5
commit 6a3d04af3d
224 changed files with 1889 additions and 36885 deletions

View File

@@ -1,134 +0,0 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Sphere.Activity;
using DysonNetwork.Sphere.Storage;
using NodaTime;
using NpgsqlTypes;
namespace DysonNetwork.Sphere.Post;
public enum PostType
{
Moment,
Article,
Video
}
public enum PostVisibility
{
Public,
Friends,
Unlisted,
Private
}
public class Post : ModelBase, IIdentifiedResource, IActivity
{
public Guid Id { get; set; }
[MaxLength(1024)] public string? Title { get; set; }
[MaxLength(4096)] public string? Description { get; set; }
[MaxLength(128)] public string? Language { get; set; }
public Instant? EditedAt { get; set; }
public Instant? PublishedAt { get; set; }
public PostVisibility Visibility { get; set; } = PostVisibility.Public;
// ReSharper disable once EntityFramework.ModelValidation.UnlimitedStringLength
public string? Content { get; set; }
public PostType Type { get; set; }
[Column(TypeName = "jsonb")] public Dictionary<string, object>? Meta { get; set; }
[Column(TypeName = "jsonb")] public List<ContentSensitiveMark>? SensitiveMarks { get; set; } = [];
public int ViewsUnique { get; set; }
public int ViewsTotal { get; set; }
public int Upvotes { get; set; }
public int Downvotes { get; set; }
[NotMapped] public Dictionary<string, int> ReactionsCount { get; set; } = new();
[NotMapped] public int RepliesCount { get; set; }
public Guid? RepliedPostId { get; set; }
public Post? RepliedPost { get; set; }
public Guid? ForwardedPostId { get; set; }
public Post? ForwardedPost { get; set; }
// Outdated fields, keep for backward compability
public ICollection<CloudFile> OutdatedAttachments { get; set; } = new List<CloudFile>();
[Column(TypeName = "jsonb")] public List<CloudFileReferenceObject> Attachments { get; set; } = [];
[JsonIgnore] public NpgsqlTsVector SearchVector { get; set; } = null!;
public Guid PublisherId { get; set; }
public Publisher.Publisher Publisher { get; set; } = null!;
public ICollection<PostReaction> Reactions { get; set; } = new List<PostReaction>();
public ICollection<PostTag> Tags { get; set; } = new List<PostTag>();
public ICollection<PostCategory> Categories { get; set; } = new List<PostCategory>();
[JsonIgnore] public ICollection<PostCollection> Collections { get; set; } = new List<PostCollection>();
[JsonIgnore] public bool Empty => Content == null && Attachments.Count == 0 && ForwardedPostId == null;
[NotMapped] public bool IsTruncated { get; set; } = false;
public string ResourceIdentifier => $"post/{Id}";
public Activity.Activity ToActivity()
{
return new Activity.Activity()
{
CreatedAt = PublishedAt ?? CreatedAt,
UpdatedAt = UpdatedAt,
DeletedAt = DeletedAt,
Id = Id,
Type = RepliedPostId is null ? "posts.new" : "posts.new.replies",
ResourceIdentifier = ResourceIdentifier,
Data = this
};
}
}
public class PostTag : ModelBase
{
public Guid Id { get; set; }
[MaxLength(128)] public string Slug { get; set; } = null!;
[MaxLength(256)] public string? Name { get; set; }
[JsonIgnore] public ICollection<Post> Posts { get; set; } = new List<Post>();
}
public class PostCategory : ModelBase
{
public Guid Id { get; set; }
[MaxLength(128)] public string Slug { get; set; } = null!;
[MaxLength(256)] public string? Name { get; set; }
[JsonIgnore] public ICollection<Post> Posts { get; set; } = new List<Post>();
}
public class PostCollection : ModelBase
{
public Guid Id { get; set; }
[MaxLength(128)] public string Slug { get; set; } = null!;
[MaxLength(256)] public string? Name { get; set; }
[MaxLength(4096)] public string? Description { get; set; }
public Publisher.Publisher Publisher { get; set; } = null!;
public ICollection<Post> Posts { get; set; } = new List<Post>();
}
public enum PostReactionAttitude
{
Positive,
Neutral,
Negative,
}
public class PostReaction : ModelBase
{
public Guid Id { get; set; }
[MaxLength(256)] public string Symbol { get; set; } = null!;
public PostReactionAttitude Attitude { get; set; }
public Guid PostId { get; set; }
[JsonIgnore] public Post Post { get; set; } = null!;
public Guid AccountId { get; set; }
public Account.Account Account { get; set; } = null!;
}

View File

@@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using DysonNetwork.Sphere.Account;
using DysonNetwork.Common.Models;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Sphere.Publisher;
using DysonNetwork.Sphere.Storage;
@@ -24,7 +24,7 @@ public class PostController(
: ControllerBase
{
[HttpGet]
public async Task<ActionResult<List<Post>>> ListPosts(
public async Task<ActionResult<List<Common.Models.Post>>> ListPosts(
[FromQuery] int offset = 0,
[FromQuery] int take = 20,
[FromQuery(Name = "pub")] string? pubName = null
@@ -63,7 +63,7 @@ public class PostController(
}
[HttpGet("{id:guid}")]
public async Task<ActionResult<Post>> GetPost(Guid id)
public async Task<ActionResult<Common.Models.Post>> GetPost(Guid id)
{
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
var currentUser = currentUserValue as Account.Account;
@@ -87,7 +87,7 @@ public class PostController(
}
[HttpGet("search")]
public async Task<ActionResult<List<Post>>> SearchPosts(
public async Task<ActionResult<List<Common.Models.Post>>> SearchPosts(
[FromQuery] string query,
[FromQuery] int offset = 0,
[FromQuery] int take = 20,
@@ -131,7 +131,7 @@ public class PostController(
}
[HttpGet("{id:guid}/replies")]
public async Task<ActionResult<List<Post>>> ListReplies(Guid id, [FromQuery] int offset = 0,
public async Task<ActionResult<List<Common.Models.Post>>> ListReplies(Guid id, [FromQuery] int offset = 0,
[FromQuery] int take = 20)
{
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
@@ -189,7 +189,7 @@ public class PostController(
[HttpPost]
[RequiredPermission("global", "posts.create")]
public async Task<ActionResult<Post>> CreatePost(
public async Task<ActionResult<Common.Models.Post>> CreatePost(
[FromBody] PostRequest request,
[FromHeader(Name = "X-Pub")] string? publisherName
)
@@ -220,7 +220,7 @@ public class PostController(
if (publisher is null) return BadRequest("Publisher was not found.");
var post = new Post
var post = new Common.Models.Post
{
Title = request.Title,
Description = request.Description,
@@ -327,7 +327,7 @@ public class PostController(
}
[HttpPatch("{id:guid}")]
public async Task<ActionResult<Post>> UpdatePost(Guid id, [FromBody] PostRequest request)
public async Task<ActionResult<Common.Models.Post>> UpdatePost(Guid id, [FromBody] PostRequest request)
{
request.Content = TextSanitizer.Sanitize(request.Content);
if (string.IsNullOrWhiteSpace(request.Content) && request.Attachments is { Count: 0 })
@@ -376,7 +376,7 @@ public class PostController(
}
[HttpDelete("{id:guid}")]
public async Task<ActionResult<Post>> DeletePost(Guid id)
public async Task<ActionResult<Common.Models.Post>> DeletePost(Guid id)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();

View File

@@ -1,5 +1,6 @@
using System.Text.RegularExpressions;
using DysonNetwork.Sphere.Account;
using DysonNetwork.Common.Models;
using DysonNetwork.Common.Services;
using DysonNetwork.Sphere.Connection.WebReader;
using DysonNetwork.Sphere.Localization;
using DysonNetwork.Sphere.Publisher;
@@ -23,7 +24,7 @@ public partial class PostService(
{
private const string PostFileUsageIdentifier = "post";
private static List<Post> TruncatePostContent(List<Post> input)
private static List<Common.Models.Post> TruncatePostContent(List<Common.Models.Post> input)
{
const int maxLength = 256;
const int embedMaxLength = 80;
@@ -53,7 +54,7 @@ public partial class PostService(
return input;
}
public (string title, string content) ChopPostForNotification(Post post)
public (string title, string content) ChopPostForNotification(Common.Models.Post post)
{
var content = !string.IsNullOrEmpty(post.Description)
? post.Description?.Length >= 40 ? post.Description[..37] + "..." : post.Description
@@ -68,9 +69,9 @@ public partial class PostService(
return (title, content);
}
public async Task<Post> PostAsync(
public async Task<Common.Models.Post> PostAsync(
Account.Account user,
Post post,
Common.Models.Post post,
List<string>? attachments = null,
List<string>? tags = null,
List<string>? categories = null
@@ -191,8 +192,8 @@ public partial class PostService(
return post;
}
public async Task<Post> UpdatePostAsync(
Post post,
public async Task<Common.Models.Post> UpdatePostAsync(
Common.Models.Post post,
List<string>? attachments = null,
List<string>? tags = null,
List<string>? categories = null,
@@ -269,7 +270,7 @@ public partial class PostService(
[GeneratedRegex(@"https?://[-A-Za-z0-9+&@#/%?=~_|!:,.;]*[-A-Za-z0-9+&@#/%=~_|]")]
private static partial Regex GetLinkRegex();
public async Task<Post> PreviewPostLinkAsync(Post item)
public async Task<Common.Models.Post> PreviewPostLinkAsync(Common.Models.Post item)
{
if (item.Type != PostType.Moment || string.IsNullOrEmpty(item.Content)) return item;
@@ -328,7 +329,7 @@ public partial class PostService(
/// This method is designed to be called from a background task
/// </summary>
/// <param name="post">The post to process link previews for</param>
private async Task ProcessPostLinkPreviewAsync(Post post)
private async Task ProcessPostLinkPreviewAsync(Common.Models.Post post)
{
try
{
@@ -367,7 +368,7 @@ public partial class PostService(
}
}
public async Task DeletePostAsync(Post post)
public async Task DeletePostAsync(Common.Models.Post post)
{
var postResourceId = $"post:{post.Id}";
@@ -389,7 +390,7 @@ public partial class PostService(
/// <param name="isSelfReact">Indicate this reaction is by the original post himself</param>
/// <param name="sender">The account that creates this reaction</param>
public async Task<bool> ModifyPostVotes(
Post post,
Common.Models.Post post,
PostReaction reaction,
Account.Account sender,
bool isRemoving,
@@ -528,10 +529,10 @@ public partial class PostService(
});
}
public async Task<List<Post>> LoadPublishers(List<Post> posts)
public async Task<List<Common.Models.Post>> LoadPublishers(List<Common.Models.Post> posts)
{
var publisherIds = posts
.SelectMany<Post, Guid?>(e =>
.SelectMany<Common.Models.Post, Guid?>(e =>
[
e.PublisherId,
e.RepliedPost?.PublisherId,
@@ -563,7 +564,7 @@ public partial class PostService(
return posts;
}
public async Task<List<Post>> LoadInteractive(List<Post> posts, Account.Account? currentUser = null)
public async Task<List<Common.Models.Post>> LoadInteractive(List<Common.Models.Post> posts, Account.Account? currentUser = null)
{
if (posts.Count == 0) return posts;
@@ -605,7 +606,7 @@ public partial class PostService(
);
}
public async Task<List<Post>> LoadPostInfo(List<Post> posts, Account.Account? currentUser = null,
public async Task<List<Common.Models.Post>> LoadPostInfo(List<Common.Models.Post> posts, Account.Account? currentUser = null,
bool truncate = false)
{
if (posts.Count == 0) return posts;
@@ -619,7 +620,7 @@ public partial class PostService(
return posts;
}
public async Task<Post> LoadPostInfo(Post post, Account.Account? currentUser = null, bool truncate = false)
public async Task<Common.Models.Post> LoadPostInfo(Common.Models.Post post, Account.Account? currentUser = null, bool truncate = false)
{
// Convert single post to list, process it, then return the single post
var posts = await LoadPostInfo([post], currentUser, truncate);
@@ -629,8 +630,8 @@ public partial class PostService(
public static class PostQueryExtensions
{
public static IQueryable<Post> FilterWithVisibility(
this IQueryable<Post> source,
public static IQueryable<Common.Models.Post> FilterWithVisibility(
this IQueryable<Common.Models.Post> source,
Account.Account? currentUser,
List<Guid> userFriends,
List<Publisher.Publisher> publishers,