Developer programs APIs

This commit is contained in:
LittleSheep 2025-06-29 18:37:23 +08:00
parent c0879d30d4
commit a53fcb10dd
2 changed files with 151 additions and 2 deletions

View File

@ -0,0 +1,148 @@
using DysonNetwork.Sphere.Account;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Sphere.Publisher;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NodaTime;
namespace DysonNetwork.Sphere.Developer;
[ApiController]
[Route("/developers")]
public class DeveloperController(
AppDatabase db,
PublisherService ps,
ActionLogService als
)
: ControllerBase
{
[HttpGet("{name}")]
public async Task<ActionResult<Publisher.Publisher>> GetDeveloper(string name)
{
var publisher = await db.Publishers
.Where(e => e.Name == name)
.FirstOrDefaultAsync();
if (publisher is null) return NotFound();
if (publisher.AccountId is null) return Ok(publisher);
var account = await db.Accounts
.Where(a => a.Id == publisher.AccountId)
.Include(a => a.Profile)
.FirstOrDefaultAsync();
publisher.Account = account;
return Ok(publisher);
}
[HttpGet("{name}/stats")]
public async Task<ActionResult<DeveloperStats>> GetDeveloperStats(string name)
{
var publisher = await db.Publishers
.Where(p => p.Name == name)
.FirstOrDefaultAsync();
if (publisher is null) return NotFound();
// Check if publisher has developer feature
var now = SystemClock.Instance.GetCurrentInstant();
var hasDeveloperFeature = await db.PublisherFeatures
.Where(f => f.PublisherId == publisher.Id)
.Where(f => f.Flag == PublisherFeatureFlag.Develop)
.Where(f => f.ExpiredAt == null || f.ExpiredAt > now)
.AnyAsync();
if (!hasDeveloperFeature) return NotFound("Not a developer account");
// Get custom apps count
var customAppsCount = await db.CustomApps
.Where(a => a.PublisherId == publisher.Id)
.CountAsync();
var stats = new DeveloperStats
{
TotalCustomApps = customAppsCount
};
return Ok(stats);
}
[HttpGet]
[Authorize]
public async Task<ActionResult<List<Publisher.Publisher>>> ListJoinedDevelopers()
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var userId = currentUser.Id;
var members = await db.PublisherMembers
.Where(m => m.AccountId == userId)
.Where(m => m.JoinedAt != null)
.Include(e => e.Publisher)
.ToListAsync();
// Filter to only include publishers with the developer feature flag
var now = SystemClock.Instance.GetCurrentInstant();
var publisherIds = members.Select(m => m.Publisher.Id).ToList();
var developerPublisherIds = await db.PublisherFeatures
.Where(f => publisherIds.Contains(f.PublisherId))
.Where(f => f.Flag == PublisherFeatureFlag.Develop)
.Where(f => f.ExpiredAt == null || f.ExpiredAt > now)
.Select(f => f.PublisherId)
.ToListAsync();
return members
.Where(m => developerPublisherIds.Contains(m.Publisher.Id))
.Select(m => m.Publisher)
.ToList();
}
[HttpPost("{name}/enroll")]
[Authorize]
[RequiredPermission("global", "developers.create")]
public async Task<ActionResult<Publisher.Publisher>> EnrollDeveloperProgram(string name)
{
if (HttpContext.Items["CurrentUser"] is not Account.Account currentUser) return Unauthorized();
var userId = currentUser.Id;
var publisher = await db.Publishers
.Where(p => p.Name == name)
.FirstOrDefaultAsync();
if (publisher is null) return NotFound();
// Check if the user is an owner of the publisher
var isOwner = await db.PublisherMembers
.AnyAsync(m =>
m.PublisherId == publisher.Id &&
m.AccountId == userId &&
m.Role == PublisherMemberRole.Owner &&
m.JoinedAt != null);
if (!isOwner) return StatusCode(403, "You must be the owner of the publisher to join the developer program");
// Check if already has a developer feature
var hasDeveloperFeature = await db.PublisherFeatures
.AnyAsync(f =>
f.PublisherId == publisher.Id &&
f.Flag == PublisherFeatureFlag.Develop &&
(f.ExpiredAt == null || f.ExpiredAt > SystemClock.Instance.GetCurrentInstant()));
if (hasDeveloperFeature) return BadRequest("Publisher is already in the developer program");
// Add developer feature flag
var feature = new PublisherFeature
{
PublisherId = publisher.Id,
Flag = PublisherFeatureFlag.Develop,
ExpiredAt = null
};
db.PublisherFeatures.Add(feature);
await db.SaveChangesAsync();
return Ok(publisher);
}
public class DeveloperStats
{
public int TotalCustomApps { get; set; }
}
}

View File

@ -35,6 +35,7 @@ public class Publisher : ModelBase, IIdentifiedResource
[JsonIgnore] public ICollection<Post.Post> Posts { get; set; } = new List<Post.Post>(); [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<PostCollection> Collections { get; set; } = new List<PostCollection>();
[JsonIgnore] public ICollection<PublisherMember> Members { get; set; } = new List<PublisherMember>(); [JsonIgnore] public ICollection<PublisherMember> Members { get; set; } = new List<PublisherMember>();
[JsonIgnore] public ICollection<PublisherFeature> Features { get; set; } = new List<PublisherFeature>();
[JsonIgnore] [JsonIgnore]
public ICollection<PublisherSubscription> Subscriptions { get; set; } = new List<PublisherSubscription>(); public ICollection<PublisherSubscription> Subscriptions { get; set; } = new List<PublisherSubscription>();
@ -98,6 +99,6 @@ public class PublisherFeature : ModelBase
public abstract class PublisherFeatureFlag public abstract class PublisherFeatureFlag
{ {
public static List<string> AllFlags => [Developer]; public static List<string> AllFlags => [Develop];
public static string Developer = "develop"; public static string Develop = "develop";
} }