// Copyright Epic Games, Inc. All Rights Reserved. using HordeServer.Api; using HordeServer.Models; using HordeServer.Services; using HordeServer.Utilities; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using MongoDB.Bson; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; namespace HordeServer.Controllers { /// /// Controller for the /api/v1/credentials endpoint /// [ApiController] [Authorize] [Route("[controller]")] public class CredentialsController : ControllerBase { /// /// Singleton instance of the ACL service /// private readonly AclService AclService; /// /// Singleton instance of the credential service /// private readonly CredentialService CredentialService; /// /// Constructor /// /// The ACL service /// The credential service public CredentialsController(AclService AclService, CredentialService CredentialService) { this.AclService = AclService; this.CredentialService = CredentialService; } /// /// Creates a new credential /// /// Parameters for the new credential. /// Http result code [HttpPost] [Route("/api/v1/credentials")] public async Task> CreateCredentialAsync([FromBody] CreateProjectRequest Create) { if(!await AclService.AuthorizeAsync(AclAction.CreateCredential, User)) { return Forbid(); } Credential NewCredential = await CredentialService.CreateCredentialAsync(Create.Name, Create.Properties); return new CreateCredentialResponse(NewCredential.Id.ToString()); } /// /// Query all the credentials /// /// Id of the credential to get information about /// Filter for the properties to return /// Information about all the credentials [HttpGet] [Route("/api/v1/credentials")] [ProducesResponseType(typeof(List), 200)] public async Task> FindCredentialAsync([FromQuery] string? Name = null, [FromQuery] PropertyFilter? Filter = null) { if (!await AclService.AuthorizeAsync(AclAction.ListCredentials, User)) { return Forbid(); } List Credentials = await CredentialService.FindCredentialsAsync(Name); GlobalPermissionsCache Cache = new GlobalPermissionsCache(); List Responses = new List(); foreach (Credential Credential in Credentials) { if (await CredentialService.AuthorizeAsync(Credential, AclAction.ViewCredential, User, Cache)) { bool bIncludeAcl = await CredentialService.AuthorizeAsync(Credential, AclAction.ViewPermissions, User, Cache); Responses.Add(new GetCredentialResponse(Credential, bIncludeAcl).ApplyFilter(Filter)); } } return Responses; } /// /// Retrieve information about a specific credential /// /// Id of the credential to get information about /// Filter for properties to return /// Information about the requested credential [HttpGet] [Route("/api/v1/credentials/{CredentialId}")] [ProducesResponseType(typeof(GetCredentialResponse), 200)] public async Task> GetCredentialAsync(string CredentialId, [FromQuery] PropertyFilter? Filter = null) { ObjectId ProjectIdValue = CredentialId.ToObjectId(); Credential? Credential = await CredentialService.GetCredentialAsync(ProjectIdValue); if (Credential == null) { return NotFound(); } GlobalPermissionsCache Cache = new GlobalPermissionsCache(); if (!await CredentialService.AuthorizeAsync(Credential, AclAction.ViewCredential, User, Cache)) { return Forbid(); } bool bIncludeAcl = await CredentialService.AuthorizeAsync(Credential, AclAction.ViewPermissions, User, Cache); return new GetCredentialResponse(Credential, bIncludeAcl).ApplyFilter(Filter); } /// /// Update a credential's properties. /// /// Id of the credential to update /// Items on the credential to update /// Http result code [HttpPut] [Route("/api/v1/credentials/{CredentialId}")] public async Task UpdateCredentialAsync(string CredentialId, [FromBody] UpdateCredentialRequest Update) { ObjectId CredentialIdValue = CredentialId.ToObjectId(); Credential? Credential = await CredentialService.GetCredentialAsync(CredentialIdValue); if(Credential == null) { return NotFound(); } GlobalPermissionsCache Cache = new GlobalPermissionsCache(); if (!await CredentialService.AuthorizeAsync(Credential, AclAction.UpdateCredential, User, Cache)) { return Forbid(); } if (Update.Acl != null && !await CredentialService.AuthorizeAsync(Credential, AclAction.ChangePermissions, User, Cache)) { return Forbid(); } await CredentialService.UpdateCredentialAsync(CredentialIdValue, Update.Name, Update.Properties, Acl.Merge(Credential.Acl, Update.Acl)); return new OkResult(); } /// /// Delete a credential /// /// Id of the credential to delete /// Http result code [HttpDelete] [Route("/api/v1/credentials/{CredentialId}")] public async Task DeleteCredentialAsync(string CredentialId) { ObjectId CredentialIdValue = CredentialId.ToObjectId(); Credential? Credential = await CredentialService.GetCredentialAsync(CredentialIdValue); if (Credential == null) { return NotFound(); } if (!await CredentialService.AuthorizeAsync(Credential, AclAction.DeleteCredential, User, null)) { return Forbid(); } if (!await CredentialService.DeleteCredentialAsync(CredentialIdValue)) { return NotFound(); } return new OkResult(); } } }