♻️ Move most of models to the Shared package
This commit is contained in:
		| @@ -1,104 +0,0 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using System.ComponentModel.DataAnnotations.Schema; | ||||
| using System.Text.Json.Serialization; | ||||
| using DysonNetwork.Sphere.Post; | ||||
| using DysonNetwork.Sphere.Storage; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using NodaTime; | ||||
|  | ||||
| namespace DysonNetwork.Sphere.Publisher; | ||||
|  | ||||
| public enum PublisherType | ||||
| { | ||||
|     Individual, | ||||
|     Organizational | ||||
| } | ||||
|  | ||||
| [Index(nameof(Name), IsUnique = true)] | ||||
| public class Publisher : ModelBase, IIdentifiedResource | ||||
| { | ||||
|     public Guid Id { get; set; } | ||||
|     public PublisherType Type { get; set; } | ||||
|     [MaxLength(256)] public string Name { get; set; } = string.Empty; | ||||
|     [MaxLength(256)] public string Nick { get; set; } = string.Empty; | ||||
|     [MaxLength(4096)] public string? Bio { get; set; } | ||||
|  | ||||
|     // Outdated fields, for backward compability | ||||
|     [MaxLength(32)] public string? PictureId { get; set; } | ||||
|     [MaxLength(32)] public string? BackgroundId { get; set; } | ||||
|  | ||||
|     [Column(TypeName = "jsonb")] public CloudFileReferenceObject? Picture { get; set; } | ||||
|     [Column(TypeName = "jsonb")] public CloudFileReferenceObject? Background { get; set; } | ||||
|  | ||||
|     [Column(TypeName = "jsonb")] public Account.VerificationMark? Verification { get; set; } | ||||
|  | ||||
|     [JsonIgnore] public ICollection<Post.Post> Posts { get; set; } = new List<Post.Post>(); | ||||
|     [JsonIgnore] public ICollection<PostCollection> Collections { get; set; } = new List<PostCollection>(); | ||||
|     [JsonIgnore] public ICollection<PublisherMember> Members { get; set; } = new List<PublisherMember>(); | ||||
|     [JsonIgnore] public ICollection<PublisherFeature> Features { get; set; } = new List<PublisherFeature>(); | ||||
|  | ||||
|     [JsonIgnore] | ||||
|     public ICollection<PublisherSubscription> Subscriptions { get; set; } = new List<PublisherSubscription>(); | ||||
|  | ||||
|     public Guid? AccountId { get; set; } | ||||
|     public Account.Account? Account { get; set; } | ||||
|     public Guid? RealmId { get; set; } | ||||
|     [JsonIgnore] public Realm.Realm? Realm { get; set; } | ||||
|  | ||||
|     public string ResourceIdentifier => $"publisher/{Id}"; | ||||
| } | ||||
|  | ||||
| public enum PublisherMemberRole | ||||
| { | ||||
|     Owner = 100, | ||||
|     Manager = 75, | ||||
|     Editor = 50, | ||||
|     Viewer = 25 | ||||
| } | ||||
|  | ||||
| public class PublisherMember : ModelBase | ||||
| { | ||||
|     public Guid PublisherId { get; set; } | ||||
|     [JsonIgnore] public Publisher Publisher { get; set; } = null!; | ||||
|     public Guid AccountId { get; set; } | ||||
|     public Account.Account Account { get; set; } = null!; | ||||
|  | ||||
|     public PublisherMemberRole Role { get; set; } = PublisherMemberRole.Viewer; | ||||
|     public Instant? JoinedAt { get; set; } | ||||
| } | ||||
|  | ||||
| public enum PublisherSubscriptionStatus | ||||
| { | ||||
|     Active, | ||||
|     Expired, | ||||
|     Cancelled | ||||
| } | ||||
|  | ||||
| public class PublisherSubscription : ModelBase | ||||
| { | ||||
|     public Guid Id { get; set; } | ||||
|  | ||||
|     public Guid PublisherId { get; set; } | ||||
|     [JsonIgnore] public Publisher Publisher { get; set; } = null!; | ||||
|     public Guid AccountId { get; set; } | ||||
|     [JsonIgnore] public Account.Account Account { get; set; } = null!; | ||||
|  | ||||
|     public PublisherSubscriptionStatus Status { get; set; } = PublisherSubscriptionStatus.Active; | ||||
|     public int Tier { get; set; } = 0; | ||||
| } | ||||
|  | ||||
| public class PublisherFeature : ModelBase | ||||
| { | ||||
|     public Guid Id { get; set; } | ||||
|     [MaxLength(1024)] public string Flag { get; set; } = null!; | ||||
|     public Instant? ExpiredAt { get; set; } | ||||
|  | ||||
|     public Guid PublisherId { get; set; } | ||||
|     public Publisher Publisher { get; set; } = null!; | ||||
| } | ||||
|  | ||||
| public abstract class PublisherFeatureFlag | ||||
| { | ||||
|     public static List<string> AllFlags => [Develop]; | ||||
|     public static string Develop = "develop"; | ||||
| } | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using DysonNetwork.Shared.Models; | ||||
| using DysonNetwork.Sphere.Account; | ||||
| using DysonNetwork.Sphere.Permission; | ||||
| using DysonNetwork.Sphere.Realm; | ||||
| @@ -20,7 +21,7 @@ public class PublisherController( | ||||
|     : ControllerBase | ||||
| { | ||||
|     [HttpGet("{name}")] | ||||
|     public async Task<ActionResult<Publisher>> GetPublisher(string name) | ||||
|     public async Task<ActionResult<Shared.Models.Publisher>> GetPublisher(string name) | ||||
|     { | ||||
|         var publisher = await db.Publishers | ||||
|             .Where(e => e.Name == name) | ||||
| @@ -47,9 +48,9 @@ public class PublisherController( | ||||
|  | ||||
|     [HttpGet] | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<List<Publisher>>> ListManagedPublishers() | ||||
|     public async Task<ActionResult<List<Shared.Models.Publisher>>> ListManagedPublishers() | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var members = await db.PublisherMembers | ||||
| @@ -65,7 +66,7 @@ public class PublisherController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<List<PublisherMember>>> ListInvites() | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var members = await db.PublisherMembers | ||||
| @@ -88,7 +89,7 @@ public class PublisherController( | ||||
|     public async Task<ActionResult<PublisherMember>> InviteMember(string name, | ||||
|         [FromBody] PublisherMemberRequest request) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var relatedUser = await db.Accounts.FindAsync(request.RelatedUserId); | ||||
| @@ -126,9 +127,9 @@ public class PublisherController( | ||||
|  | ||||
|     [HttpPost("invites/{name}/accept")] | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<Publisher>> AcceptMemberInvite(string name) | ||||
|     public async Task<ActionResult<Shared.Models.Publisher>> AcceptMemberInvite(string name) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var member = await db.PublisherMembers | ||||
| @@ -154,7 +155,7 @@ public class PublisherController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult> DeclineMemberInvite(string name) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var member = await db.PublisherMembers | ||||
| @@ -179,7 +180,7 @@ public class PublisherController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult> RemoveMember(string name, Guid memberId) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var publisher = await db.Publishers | ||||
|             .Where(p => p.Name == name) | ||||
| @@ -222,9 +223,9 @@ public class PublisherController( | ||||
|     [HttpPost("individual")] | ||||
|     [Authorize] | ||||
|     [RequiredPermission("global", "publishers.create")] | ||||
|     public async Task<ActionResult<Publisher>> CreatePublisherIndividual([FromBody] PublisherRequest request) | ||||
|     public async Task<ActionResult<Shared.Models.Publisher>> CreatePublisherIndividual([FromBody] PublisherRequest request) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var takenName = request.Name ?? currentUser.Name; | ||||
|         var duplicateNameCount = await db.Publishers | ||||
| @@ -271,10 +272,10 @@ public class PublisherController( | ||||
|     [HttpPost("organization/{realmSlug}")] | ||||
|     [Authorize] | ||||
|     [RequiredPermission("global", "publishers.create")] | ||||
|     public async Task<ActionResult<Publisher>> CreatePublisherOrganization(string realmSlug, | ||||
|     public async Task<ActionResult<Shared.Models.Publisher>> CreatePublisherOrganization(string realmSlug, | ||||
|         [FromBody] PublisherRequest request) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var realm = await db.Realms.FirstOrDefaultAsync(r => r.Slug == realmSlug); | ||||
|         if (realm == null) return NotFound("Realm not found"); | ||||
| @@ -326,9 +327,9 @@ public class PublisherController( | ||||
|  | ||||
|     [HttpPatch("{name}")] | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<Publisher>> UpdatePublisher(string name, PublisherRequest request) | ||||
|     public async Task<ActionResult<Shared.Models.Publisher>> UpdatePublisher(string name, PublisherRequest request) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var publisher = await db.Publishers | ||||
| @@ -403,9 +404,9 @@ public class PublisherController( | ||||
|  | ||||
|     [HttpDelete("{name}")] | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<Publisher>> DeletePublisher(string name) | ||||
|     public async Task<ActionResult<Shared.Models.Publisher>> DeletePublisher(string name) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var publisher = await db.Publishers | ||||
| @@ -473,7 +474,7 @@ public class PublisherController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<PublisherMember>> GetCurrentIdentity(string name) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|         var userId = currentUser.Id; | ||||
|  | ||||
|         var publisher = await db.Publishers | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| using DysonNetwork.Shared.Models; | ||||
| using DysonNetwork.Sphere.Post; | ||||
| using DysonNetwork.Sphere.Storage; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| @@ -8,7 +9,7 @@ namespace DysonNetwork.Sphere.Publisher; | ||||
|  | ||||
| public class PublisherService(AppDatabase db, FileReferenceService fileRefService, ICacheService cache) | ||||
| { | ||||
|     public async Task<Publisher?> GetPublisherByName(string name) | ||||
|     public async Task<Shared.Models.Publisher?> GetPublisherByName(string name) | ||||
|     { | ||||
|         return await db.Publishers | ||||
|             .Where(e => e.Name == name) | ||||
| @@ -17,12 +18,12 @@ public class PublisherService(AppDatabase db, FileReferenceService fileRefServic | ||||
|  | ||||
|     private const string UserPublishersCacheKey = "accounts:{0}:publishers"; | ||||
|  | ||||
|     public async Task<List<Publisher>> GetUserPublishers(Guid userId) | ||||
|     public async Task<List<Shared.Models.Publisher>> GetUserPublishers(Guid userId) | ||||
|     { | ||||
|         var cacheKey = string.Format(UserPublishersCacheKey, userId); | ||||
|          | ||||
|         // Try to get publishers from the cache first | ||||
|         var publishers = await cache.GetAsync<List<Publisher>>(cacheKey); | ||||
|         var publishers = await cache.GetAsync<List<Shared.Models.Publisher>>(cacheKey); | ||||
|         if (publishers is not null) | ||||
|             return publishers; | ||||
|          | ||||
| @@ -41,16 +42,16 @@ public class PublisherService(AppDatabase db, FileReferenceService fileRefServic | ||||
|         return publishers; | ||||
|     } | ||||
|  | ||||
|     public async Task<Dictionary<Guid, List<Publisher>>> GetUserPublishersBatch(List<Guid> userIds) | ||||
|     public async Task<Dictionary<Guid, List<Shared.Models.Publisher>>> GetUserPublishersBatch(List<Guid> userIds) | ||||
|     { | ||||
|         var result = new Dictionary<Guid, List<Publisher>>(); | ||||
|         var result = new Dictionary<Guid, List<Shared.Models.Publisher>>(); | ||||
|         var missingIds = new List<Guid>(); | ||||
|  | ||||
|         // Try to get publishers from cache for each user | ||||
|         foreach (var userId in userIds) | ||||
|         { | ||||
|             var cacheKey = string.Format(UserPublishersCacheKey, userId); | ||||
|             var publishers = await cache.GetAsync<List<Publisher>>(cacheKey); | ||||
|             var publishers = await cache.GetAsync<List<Shared.Models.Publisher>>(cacheKey); | ||||
|             if (publishers != null) | ||||
|                 result[userId] = publishers; | ||||
|             else | ||||
| @@ -97,12 +98,12 @@ public class PublisherService(AppDatabase db, FileReferenceService fileRefServic | ||||
|  | ||||
|     public const string SubscribedPublishersCacheKey = "accounts:{0}:subscribed-publishers"; | ||||
|      | ||||
|     public async Task<List<Publisher>> GetSubscribedPublishers(Guid userId) | ||||
|     public async Task<List<Shared.Models.Publisher>> GetSubscribedPublishers(Guid userId) | ||||
|     { | ||||
|         var cacheKey = string.Format(SubscribedPublishersCacheKey, userId); | ||||
|  | ||||
|         // Try to get publishers from the cache first | ||||
|         var publishers = await cache.GetAsync<List<Publisher>>(cacheKey); | ||||
|         var publishers = await cache.GetAsync<List<Shared.Models.Publisher>>(cacheKey); | ||||
|         if (publishers is not null) | ||||
|             return publishers; | ||||
|  | ||||
| @@ -146,8 +147,8 @@ public class PublisherService(AppDatabase db, FileReferenceService fileRefServic | ||||
|         return members; | ||||
|     } | ||||
|      | ||||
|     public async Task<Publisher> CreateIndividualPublisher( | ||||
|         Account.Account account, | ||||
|     public async Task<Shared.Models.Publisher> CreateIndividualPublisher( | ||||
|         Shared.Models.Account account, | ||||
|         string? name, | ||||
|         string? nick, | ||||
|         string? bio, | ||||
| @@ -155,7 +156,7 @@ public class PublisherService(AppDatabase db, FileReferenceService fileRefServic | ||||
|         CloudFile? background | ||||
|     ) | ||||
|     { | ||||
|         var publisher = new Publisher | ||||
|         var publisher = new Shared.Models.Publisher | ||||
|         { | ||||
|             Type = PublisherType.Individual, | ||||
|             Name = name ?? account.Name, | ||||
| @@ -199,9 +200,9 @@ public class PublisherService(AppDatabase db, FileReferenceService fileRefServic | ||||
|         return publisher; | ||||
|     } | ||||
|  | ||||
|     public async Task<Publisher> CreateOrganizationPublisher( | ||||
|         Realm.Realm realm, | ||||
|         Account.Account account, | ||||
|     public async Task<Shared.Models.Publisher> CreateOrganizationPublisher( | ||||
|         Shared.Models.Realm realm, | ||||
|         Shared.Models.Account account, | ||||
|         string? name, | ||||
|         string? nick, | ||||
|         string? bio, | ||||
| @@ -209,7 +210,7 @@ public class PublisherService(AppDatabase db, FileReferenceService fileRefServic | ||||
|         CloudFile? background | ||||
|     ) | ||||
|     { | ||||
|         var publisher = new Publisher | ||||
|         var publisher = new Shared.Models.Publisher | ||||
|         { | ||||
|             Type = PublisherType.Organizational, | ||||
|             Name = name ?? realm.Slug, | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| using DysonNetwork.Shared.Models; | ||||
| using DysonNetwork.Sphere.Post; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| @@ -30,7 +31,7 @@ public class PublisherSubscriptionController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<SubscriptionStatusResponse>> CheckSubscriptionStatus(string name) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|      | ||||
|         // Check if the publisher exists | ||||
|         var publisher = await db.Publishers.FirstOrDefaultAsync(p => p.Name == name); | ||||
| @@ -53,7 +54,7 @@ public class PublisherSubscriptionController( | ||||
|         string name, | ||||
|         [FromBody] SubscribeRequest request) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|      | ||||
|         // Check if the publisher exists | ||||
|         var publisher = await db.Publishers.FirstOrDefaultAsync(p => p.Name == name); | ||||
| @@ -81,7 +82,7 @@ public class PublisherSubscriptionController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult> Unsubscribe(string name) | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         // Check if the publisher exists | ||||
|         var publisher = await db.Publishers.FirstOrDefaultAsync(e => e.Name == name); | ||||
| @@ -104,7 +105,7 @@ public class PublisherSubscriptionController( | ||||
|     [Authorize] | ||||
|     public async Task<ActionResult<List<PublisherSubscription>>> GetCurrentSubscriptions() | ||||
|     { | ||||
|         if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized(); | ||||
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized(); | ||||
|  | ||||
|         var subscriptions = await subs.GetAccountSubscriptionsAsync(currentUser.Id); | ||||
|         return subscriptions; | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| using DysonNetwork.Shared.Models; | ||||
| using DysonNetwork.Sphere.Account; | ||||
| using DysonNetwork.Sphere.Localization; | ||||
| using DysonNetwork.Sphere.Post; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user