diff --git a/server/Controllers/RvrController.cs b/server/Controllers/RvrController.cs new file mode 100644 index 0000000..2903be8 --- /dev/null +++ b/server/Controllers/RvrController.cs @@ -0,0 +1,180 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Logging; +using Microsoft.EntityFrameworkCore; +using System.Linq; +using Sockeye.Models; +using Sockeye.Biz; +using Sockeye.Api.ControllerHelpers; +using System.ComponentModel.DataAnnotations; + +namespace Sockeye.Api.Controllers +{ + [Route("rvr")]//v8 fetch license route + [Produces("application/json")] + public class RvrController : ControllerBase + { + + private readonly AyContext ct; + private readonly ILogger log; + private readonly ApiServerState serverState; + + /// + /// ctor + /// + /// + /// + /// + public RvrController(AyContext dbcontext, ILogger logger, ApiServerState apiServerState) + { + ct = dbcontext; + log = logger; + serverState = apiServerState; + } + + public class dtoRequest + { + [Required] + public string DbId { get; set; } + public bool Perpetual { get; set; } = true;//not required and default true to not break any older beta testers out there, can set to required in future + [Required, EmailAddress] + public string Email { get; set; } + [Required] + public string Company { get; set; } + [Required] + public string Contact { get; set; } + } + +#if (DEBUG) + private const string LICENSE_SERVER_URL = "http://localhost:3001/"; + public const string SUPPORT_EMAIL = "cardjohn@ayanova.com"; +#else + private const string LICENSE_SERVER_URL = "https://rockfish.ayanova.com/"; + public const string SUPPORT_EMAIL="support@ayanova.com"; +#endif + + //######################################################### + //REQUEST TRIAL ROUTE CALLED FROM RAVEN + //######################################################### + [HttpPost] + public async Task Post([FromBody] dtoRequest r) + { + if (!serverState.IsOpen) + return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason)); + + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + // if (r.DbId == Guid.Empty) + if (string.IsNullOrWhiteSpace(r.DbId)) + { + return BadRequest("E1000 - DBId invalid"); + } + + //can't do this if there is a purchased license with this dbid already + if (await ct.License.Where(z => z.DbId == r.DbId).AnyAsync()) + { + return BadRequest("E1000 - Can't trial; there is already a purchased license issued for this database Id"); + } + + //can't do this if there is a trial request already pending + if (await ct.TrialLicenseRequest.Where(z => z.DbId == r.DbId + && z.Status != Biz.TrialRequestStatus.Approved + && z.Status != Biz.TrialRequestStatus.Rejected).AnyAsync()) + { + return Ok("Request awaiting approval"); + } + + + //Everything seems to be in order, save the request and return ok + var newObject = new TrialLicenseRequest(); + newObject.Email = r.Email; + newObject.DbId = r.DbId; + newObject.CompanyName = r.Company; + newObject.ContactName = r.Contact; + newObject.PGroup = r.Perpetual ? Biz.ProductGroup.RavenPerpetual : Biz.ProductGroup.RavenSubscription; + + TrialLicenseRequestBiz biz = TrialLicenseRequestBiz.GetBiz(ct); + TrialLicenseRequest o = await biz.CreateAsync(newObject); + if (o == null) + { + var msg = ($"Unexpected error (code SE-444 was returned to customer) processing a new trial license request:{biz.GetErrorsAsString}"); + log.LogError(msg); + await NotifyEventHelper.AddOpsProblemEvent(msg); + return BadRequest($"E1000 - Error processing request code SE-444 contact support");//don't want to leak any info so need to check sockeye log if get this error + } + else + return Accepted(); + } + + //### CUSTOMER ROUTE CALLED FROM CUSTOMER BROWSER / EMAIL #### + [HttpGet("verify/{code}")] + public async Task GetVerify([FromRoute] string code) + { + if (!serverState.IsOpen) + return new ContentResult + { + ContentType = "text/html", + StatusCode = 503, + Content = "

Service temporarily unavailable

This service is temporarily down for maintenance please try again shortly.

" + }; + + + //is there a valid trial request + var req = await ct.TrialLicenseRequest.AsNoTracking().Where(z => z.EmailConfirmCode == code && z.Status == TrialRequestStatus.AwaitingEmailValidation).FirstOrDefaultAsync(); + if (req == null) + { + return new ContentResult + { + ContentType = "text/html", + StatusCode = 200, + Content = "

Request not found

There was no evaluation request associated with this verification code or it was already validated.

" + }; + } + + TrialLicenseRequestBiz biz = TrialLicenseRequestBiz.GetBiz(ct); + var tlr = await biz.GetAsync(req.Id); + if (tlr == null) + { + //this should never happen unless maybe it was *just* validated a moment after this is repeat called?! + return new ContentResult + { + ContentType = "text/html", + StatusCode = 200, + Content = "

Request not found

There was no evaluation request associated with this verification code or it was already validated.

" + }; + } + + tlr.Status = TrialRequestStatus.AwaitingApproval; + tlr.EmailValidated = true; + var res = await biz.PutAsync(tlr); + if (res == null) + { + var msg = ($"Unexpected error processing a trial license request after email validation:{biz.GetErrorsAsString}"); + log.LogError(msg); + await NotifyEventHelper.AddOpsProblemEvent(msg); + return new ContentResult + { + ContentType = "text/html", + StatusCode = 503, + Content = "

Error processing request

There was an internal error processing your request. Please try again or contact Support.

" + }; + } + + + return new ContentResult + { + ContentType = "text/html", + StatusCode = 200, + Content = "

Email validated!

Your request will be reviewed and processed by our staff during business hours. You will receive an email with instructions for starting your AyaNova evaluation.

" + }; + } + + //------------ + + + }//eoc +}//eons \ No newline at end of file diff --git a/server/biz/TrialLicenseRequestBiz.cs b/server/biz/TrialLicenseRequestBiz.cs index 19558a3..367fb1a 100644 --- a/server/biz/TrialLicenseRequestBiz.cs +++ b/server/biz/TrialLicenseRequestBiz.cs @@ -66,7 +66,7 @@ namespace Sockeye.Biz //ValidateEmail request message,RavenTrialApproved (which sends pending manual generation message) and RavenTrialRejected messages are sent in this block // //Send verification request - var verifyUrl = ServerGlobalOpsSettingsCache.Notify.SockeyeServerURL.Trim().TrimEnd('/') + $"/trial-license-request/verify/{newObject.EmailConfirmCode}"; + var verifyUrl = ServerGlobalOpsSettingsCache.Notify.SockeyeServerURL.Trim().TrimEnd('/') + $"/rvr/verify/{newObject.EmailConfirmCode}"; var body = ServerGlobalBizSettings.Cache.ValidateEmail.Replace("{verifyUrl}", verifyUrl);//$"Please verify your email address by clicking the link below or copy and pasting into a browser\r\n{verifyUrl}\r\nOnce your email is verified the request will be processed manually during business hours.\r\n(If you did not request this you can ignore this message)"; var notifyDirectSMTP = new Sockeye.Api.Controllers.NotifyController.NotifyDirectSMTP() @@ -250,7 +250,7 @@ namespace Sockeye.Biz ct.Replace(dbObject, putObject); try - { + { await ct.SaveChangesAsync(); } catch (DbUpdateConcurrencyException) @@ -360,10 +360,13 @@ namespace Sockeye.Biz private async Task ValidateAsync(TrialLicenseRequest proposedObj, TrialLicenseRequest currentObj) { + //no need to validate required fields, they are set to required in the model with an attribute + //no need to validate required fields, they are set to required in the model with an attribute + //no need to validate required fields, they are set to required in the model with an attribute await Task.CompletedTask; // bool isNew = currentObj == null; - - + //no need to validate required fields, they are set to required in the model with an attribute + //no need to validate required fields, they are set to required in the model with an attribute //no need to validate required fields, they are set to required in the model with an attribute