// ========================================================================== // Squidex Headless CMS // ========================================================================== // Copyright (c) Squidex UG (haftungsbeschraenkt) // All rights reserved. Licensed under the MIT license. // ========================================================================== using Microsoft.AspNetCore.Mvc; using Microsoft.Net.Http.Headers; using Squidex.Areas.Api.Controllers.Apps.Models; using Squidex.Domain.Apps.Entities.Apps; using Squidex.Domain.Apps.Entities.Apps.Commands; using Squidex.Infrastructure.Commands; using Squidex.Shared; using Squidex.Web; namespace Squidex.Areas.Api.Controllers.Apps { /// /// Manages and configures apps. /// [ApiExplorerSettings(GroupName = nameof(Apps))] public sealed class AppClientsController : ApiController { public AppClientsController(ICommandBus commandBus) : base(commandBus) { } /// /// Get app clients. /// /// The name of the app. /// /// 200 => Clients returned. /// 404 => App not found. /// /// /// Gets all configured clients for the app with the specified name. /// [HttpGet] [Route("apps/{app}/clients/")] [ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(PermissionIds.AppClientsRead)] [ApiCosts(0)] public IActionResult GetClients(string app) { var response = Deferred.Response(() => { return GetResponse(App); }); Response.Headers[HeaderNames.ETag] = App.ToEtag(); return Ok(response); } /// /// Create a new app client. /// /// The name of the app. /// Client object that needs to be added to the app. /// /// 201 => Client created. /// 400 => Client request not valid. /// 404 => App not found. /// /// /// Create a new client for the app with the specified name. /// The client secret is auto generated on the server and returned. The client does not expire, the access token is valid for 30 days. /// [HttpPost] [Route("apps/{app}/clients/")] [ProducesResponseType(typeof(ClientsDto), 201)] [ApiPermissionOrAnonymous(PermissionIds.AppClientsCreate)] [ApiCosts(1)] public async Task PostClient(string app, [FromBody] CreateClientDto request) { var command = request.ToCommand(); var response = await InvokeCommandAsync(command); return CreatedAtAction(nameof(GetClients), new { app }, response); } /// /// Updates an app client. /// /// The name of the app. /// The id of the client that must be updated. /// Client object that needs to be updated. /// /// 200 => Client updated. /// 400 => Client request not valid. /// 404 => Client or app not found. /// /// /// Only the display name can be changed, create a new client if necessary. /// [HttpPut] [Route("apps/{app}/clients/{id}/")] [ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(PermissionIds.AppClientsUpdate)] [ApiCosts(1)] public async Task PutClient(string app, string id, [FromBody] UpdateClientDto request) { var command = request.ToCommand(id); var response = await InvokeCommandAsync(command); return Ok(response); } /// /// Revoke an app client. /// /// The name of the app. /// The id of the client that must be deleted. /// /// 200 => Client deleted. /// 404 => Client or app not found. /// /// /// The application that uses this client credentials cannot access the API after it has been revoked. /// [HttpDelete] [Route("apps/{app}/clients/{id}/")] [ProducesResponseType(typeof(ClientsDto), StatusCodes.Status200OK)] [ApiPermissionOrAnonymous(PermissionIds.AppClientsDelete)] [ApiCosts(1)] public async Task DeleteClient(string app, string id) { var command = new RevokeClient { Id = id }; var response = await InvokeCommandAsync(command); return Ok(response); } private async Task InvokeCommandAsync(ICommand command) { var context = await CommandBus.PublishAsync(command, HttpContext.RequestAborted); var result = context.Result(); var response = GetResponse(result); return response; } private ClientsDto GetResponse(IAppEntity app) { return ClientsDto.FromApp(app, Resources); } } }