✨ Developer programs APIs
This commit is contained in:
parent
c0879d30d4
commit
a53fcb10dd
148
DysonNetwork.Sphere/Developer/DeveloperController.cs
Normal file
148
DysonNetwork.Sphere/Developer/DeveloperController.cs
Normal 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; }
|
||||||
|
}
|
||||||
|
}
|
@ -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";
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user