using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Routing; using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Logging; using AyaNova.Models; using AyaNova.Api.ControllerHelpers; using AyaNova.Biz; using System.ComponentModel.DataAnnotations; namespace AyaNova.Api.Controllers { /// /// License route /// [ApiController] [ApiVersion("8.0")] [Route("api/v{version:apiVersion}/license")] [Produces("application/json")] [Authorize] public class LicenseController : ControllerBase { private readonly AyContext ct; private readonly ILogger log; private readonly ApiServerState serverState; /// /// ctor /// /// /// /// public LicenseController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) { ct = dbcontext; log = logger; serverState = apiServerState; } /// /// Get License info /// /// Information about the currently installed license in AyaNova [HttpGet()] public ActionResult GetLicenseInfo() { if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!Authorized.HasReadFullRole(HttpContext.Items, AyaType.License)) { return StatusCode(403, new ApiNotAuthorizedResponse()); } var ret = AyaNova.Core.License.LicenseInfoAsJson; return Ok(ApiOkResponse.Response(ret)); } // /// // /// Get Trial status of license // /// // /// True if a trial license // [AllowAnonymous] // [HttpGet("trial")] // public ActionResult GetTrialFlag() // { // //note: this route is called by the client as the first action so it also acts like a ping to see if the server is up as well // if (serverState.IsClosed) // return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); // return Ok(ApiOkResponse.Response(AyaNova.Core.License.ActiveKey.TrialLicense)); // } /// /// Fetch license /// /// Posting to this route causes AyaNova to attempt to refresh it's license /// from the AyaNova license server /// /// On success returns information about the currently installed license in AyaNova [HttpPost] public async Task FetchLicense() { if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!Authorized.HasCreateRole(HttpContext.Items, AyaType.License)) { return StatusCode(403, new ApiNotAuthorizedResponse()); } if (!ModelState.IsValid) { return BadRequest(new ApiErrorResponse(ModelState)); } try { await AyaNova.Core.License.FetchKeyAsync(serverState, ct, log); } catch (Exception ex) { Exception rootex = ex; while (rootex.InnerException != null) { rootex = rootex.InnerException; } if (rootex.Message.Contains("E1020")) { return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, "LICENSE_KEY", rootex.Message)); } else { throw ex; } } var ret = AyaNova.Core.License.LicenseInfoAsJson; //Log await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseFetch), ct); return Ok(ApiOkResponse.Response(ret)); } /// /// Request trial license /// /// Posting to this route causes AyaNova to request a trial license key from the AyaNova license server /// Database must be empty and unlicensed or trial license /// /// /// HTTP 204 No Content result code on success or fail code with explanation [HttpPost("trialRequest")] public async Task RequestTrial([FromBody] RequestTrial trialRequest) { if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!Authorized.HasCreateRole(HttpContext.Items, AyaType.License)) { return StatusCode(403, new ApiNotAuthorizedResponse()); } if (!ModelState.IsValid) { return BadRequest(new ApiErrorResponse(ModelState)); } if (!await AyaNova.Util.DbUtil.DBIsEmptyAsync(ct, log)) { return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "Only an empty AyaNova database can request a trial key. Erase the database to proceed with a new trial.")); } if (!AyaNova.Core.License.ActiveKey.IsEmpty && !AyaNova.Core.License.ActiveKey.TrialLicense) { return BadRequest(new ApiErrorResponse(ApiErrorCode.INVALID_OPERATION, null, "There is an active registered license. Only an unlicensed or trial license database can request a trial key.")); } //Send the request to RockFish here (or at least start the job to do it in which case return Accepted instead of no content and update comment above) var ret = await Core.License.RequestTrialAsync(trialRequest, log); //Log await EventLogProcessor.LogEventToDatabaseAsync(new Event(UserIdFromContext.Id(HttpContext.Items), 0, AyaType.License, AyaEvent.LicenseTrialRequest), ct); return Ok(ApiOkResponse.Response(ret)); } /// /// Permanently erase all data and all attachments /// /// Posting to this route causes AyaNova completely erase all data in it's database and erase all attachment files /// returning the database to an empty state /// /// The only items retained are the SuperUser account and the license key /// /// (Only *the* SuperUser account can use this route) /// /// Must be "I understand" /// HTTP 204 No Content result code on success or fail code with explanation [HttpPost("permanently-erase-all-data")] public async Task RemoveAllData([FromBody] string acceptCode) { if (serverState.IsClosed) return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); if (!ModelState.IsValid) return BadRequest(new ApiErrorResponse(ModelState)); long UserId = UserIdFromContext.Id(HttpContext.Items); //SuperUser only and must have accept code if (UserId != 1 || string.IsNullOrWhiteSpace(acceptCode) || acceptCode.ToLowerInvariant() != "i understand") return StatusCode(403, new ApiNotAuthorizedResponse()); //empty the db await AyaNova.Util.DbUtil.EmptyBizDataFromDatabaseForSeedingOrImportingAsync(log); //Log await EventLogProcessor.LogEventToDatabaseAsync(new Event(1, 0, AyaType.Global, AyaEvent.EraseAllData), ct); return NoContent(); } //------------------------------------------------------ }//eoc }//eons