130 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System.ComponentModel.DataAnnotations;
 | |
| using DysonNetwork.Shared.Models;
 | |
| using DysonNetwork.Sphere.Account;
 | |
| using DysonNetwork.Sphere.Publisher;
 | |
| using Microsoft.AspNetCore.Authorization;
 | |
| using Microsoft.AspNetCore.Mvc;
 | |
| 
 | |
| namespace DysonNetwork.Sphere.Developer;
 | |
| 
 | |
| [ApiController]
 | |
| [Route("/developers/{pubName}/apps")]
 | |
| public class CustomAppController(CustomAppService customApps, PublisherService ps) : ControllerBase
 | |
| {
 | |
|     public record CustomAppRequest(
 | |
|         [MaxLength(1024)] string? Slug,
 | |
|         [MaxLength(1024)] string? Name,
 | |
|         [MaxLength(4096)] string? Description,
 | |
|         string? PictureId,
 | |
|         string? BackgroundId,
 | |
|         CustomAppStatus? Status,
 | |
|         CustomAppLinks? Links,
 | |
|         CustomAppOauthConfig? OauthConfig
 | |
|     );
 | |
| 
 | |
|     [HttpGet]
 | |
|     public async Task<IActionResult> ListApps([FromRoute] string pubName)
 | |
|     {
 | |
|         var publisher = await ps.GetPublisherByName(pubName);
 | |
|         if (publisher is null) return NotFound();
 | |
|         var apps = await customApps.GetAppsByPublisherAsync(publisher.Id);
 | |
|         return Ok(apps);
 | |
|     }
 | |
| 
 | |
|     [HttpGet("{id:guid}")]
 | |
|     public async Task<IActionResult> GetApp([FromRoute] string pubName, Guid id)
 | |
|     {
 | |
|         var publisher = await ps.GetPublisherByName(pubName);
 | |
|         if (publisher is null) return NotFound();
 | |
| 
 | |
|         var app = await customApps.GetAppAsync(id, publisherId: publisher.Id);
 | |
|         if (app == null)
 | |
|             return NotFound();
 | |
| 
 | |
|         return Ok(app);
 | |
|     }
 | |
| 
 | |
|     [HttpPost]
 | |
|     [Authorize]
 | |
|     public async Task<IActionResult> CreateApp([FromRoute] string pubName, [FromBody] CustomAppRequest request)
 | |
|     {
 | |
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
 | |
| 
 | |
|         if (string.IsNullOrWhiteSpace(request.Name) || string.IsNullOrWhiteSpace(request.Slug))
 | |
|             return BadRequest("Name and slug are required");
 | |
| 
 | |
|         var publisher = await ps.GetPublisherByName(pubName);
 | |
|         if (publisher is null) return NotFound();
 | |
| 
 | |
|         if (!await ps.IsMemberWithRole(publisher.Id, currentUser.Id, PublisherMemberRole.Editor))
 | |
|             return StatusCode(403, "You must be an editor of the publisher to create a custom app");
 | |
|         if (!await ps.HasFeature(publisher.Id, PublisherFeatureFlag.Develop))
 | |
|             return StatusCode(403, "Publisher must be a developer to create a custom app");
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             var app = await customApps.CreateAppAsync(publisher, request);
 | |
|             return Ok(app);
 | |
|         }
 | |
|         catch (InvalidOperationException ex)
 | |
|         {
 | |
|             return BadRequest(ex.Message);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     [HttpPatch("{id:guid}")]
 | |
|     [Authorize]
 | |
|     public async Task<IActionResult> UpdateApp(
 | |
|         [FromRoute] string pubName,
 | |
|         [FromRoute] Guid id,
 | |
|         [FromBody] CustomAppRequest request
 | |
|     )
 | |
|     {
 | |
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
 | |
|         
 | |
|         var publisher = await ps.GetPublisherByName(pubName);
 | |
|         if (publisher is null) return NotFound();
 | |
|         
 | |
|         if (!await ps.IsMemberWithRole(publisher.Id, currentUser.Id, PublisherMemberRole.Editor))
 | |
|             return StatusCode(403, "You must be an editor of the publisher to update a custom app");
 | |
| 
 | |
|         var app = await customApps.GetAppAsync(id, publisherId: publisher.Id);
 | |
|         if (app == null)
 | |
|             return NotFound();
 | |
| 
 | |
|         try
 | |
|         {
 | |
|             app = await customApps.UpdateAppAsync(app, request);
 | |
|             return Ok(app);
 | |
|         }
 | |
|         catch (InvalidOperationException ex)
 | |
|         {
 | |
|             return BadRequest(ex.Message);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     [HttpDelete("{id:guid}")]
 | |
|     [Authorize]
 | |
|     public async Task<IActionResult> DeleteApp(
 | |
|         [FromRoute] string pubName,
 | |
|         [FromRoute] Guid id
 | |
|     )
 | |
|     {
 | |
|         if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
 | |
|         
 | |
|         var publisher = await ps.GetPublisherByName(pubName);
 | |
|         if (publisher is null) return NotFound();
 | |
|         
 | |
|         if (!await ps.IsMemberWithRole(publisher.Id, currentUser.Id, PublisherMemberRole.Editor))
 | |
|             return StatusCode(403, "You must be an editor of the publisher to delete a custom app");
 | |
| 
 | |
|         var app = await customApps.GetAppAsync(id, publisherId: publisher.Id);
 | |
|         if (app == null)
 | |
|             return NotFound();
 | |
| 
 | |
|         var result = await customApps.DeleteAppAsync(id);
 | |
|         if (!result)
 | |
|             return NotFound();
 | |
|         return NoContent();
 | |
|     }
 | |
| } |