This commit is contained in:
@@ -38,10 +38,10 @@ namespace rockfishCore.Controllers
|
||||
|
||||
#if (DEBUG)
|
||||
private const string LICENSE_SERVER_URL = "http://localhost:3001/";
|
||||
private const string SUPPORT_EMAIL = "cardjohn@ayanova.com";
|
||||
public const string SUPPORT_EMAIL = "cardjohn@ayanova.com";
|
||||
#else
|
||||
private const string LICENSE_SERVER_URL = "https://rockfish.ayanova.com/";
|
||||
private const string SUPPORT_EMAIL="support@ayanova.com";
|
||||
public const string SUPPORT_EMAIL="support@ayanova.com";
|
||||
#endif
|
||||
|
||||
[HttpPost]
|
||||
@@ -66,7 +66,7 @@ namespace rockfishCore.Controllers
|
||||
System.Diagnostics.Debug.WriteLine("RvRController:Post - TODO: Test MustBeOlderThan date code");
|
||||
|
||||
//if there is an active trial for this db then can't do this they must request we re-release it or completely zap the database instead
|
||||
var MustBeOlderThan = DateUtil.DateToEpoch(DateTime.Now.AddDays(-45));
|
||||
var MustBeOlderThan = DateUtil.DateToEpoch(DateTime.Now.AddDays((RavenKeyFactory.TRIAL_PERIOD_DAYS * -1)));
|
||||
if (await ct.TrialRequest.Where(z => z.DbId == r.DbId && z.DtProcessed != null && z.DtProcessed > MustBeOlderThan).AnyAsync())
|
||||
{
|
||||
return BadRequest("E1000 - Can't trial; there is already an active trial license issued for this database Id");
|
||||
@@ -114,7 +114,7 @@ namespace rockfishCore.Controllers
|
||||
var rfUrl = LICENSE_SERVER_URL + $"default.htm#!/trialEdit/{req.Id}";
|
||||
var body = $"Email address {req.Email} was just verified for {req.ContactName} at {req.CompanyName}.\r\nTrial key is ready to be processed now:\r\n{rfUrl}";
|
||||
//send confirmation email
|
||||
RfMail.SendMessage("support@ayanova.com", "support@ayanova.com", "AyaNova trial request requiring action", body, false);
|
||||
RfMail.SendMessage("support@ayanova.com", SUPPORT_EMAIL, "AyaNova trial request requiring action", body, false);
|
||||
|
||||
return new ContentResult
|
||||
{
|
||||
|
||||
@@ -5,7 +5,7 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
using rockfishCore.Util;
|
||||
|
||||
namespace rockfishCore.Controllers
|
||||
{
|
||||
@@ -65,44 +65,74 @@ namespace rockfishCore.Controllers
|
||||
return Ok(rec);
|
||||
}
|
||||
|
||||
|
||||
// PUT: api/TrialRequest/5
|
||||
[HttpPut("{id}")]
|
||||
public async Task<IActionResult> PutTrialRequest([FromRoute] long id, [FromBody] TrialRequest TrialRequest)
|
||||
//Approve
|
||||
[HttpPost("approve/{id}")]
|
||||
public async Task<IActionResult> ApproveTrial([FromRoute] long id)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return BadRequest(ModelState);
|
||||
var trial = await ct.TrialRequest.SingleOrDefaultAsync(m => m.Id == id);
|
||||
if (trial == null)
|
||||
return NotFound();
|
||||
//DO APPROVE
|
||||
//check not already processed and ignore if so
|
||||
if(trial.DtProcessed!=null){
|
||||
//already processed, nothing to do here
|
||||
return BadRequest("Already processed");
|
||||
}
|
||||
|
||||
if (id != TrialRequest.Id)
|
||||
{
|
||||
return BadRequest();
|
||||
}
|
||||
//generate license key and insert in record
|
||||
trial.Key = RavenKeyFactory.GetRavenTrialKey(trial.DbId, trial.CompanyName);
|
||||
trial.Status = TrialRequest.TrialRequestStatus.Approved;
|
||||
trial.DtProcessed = DateUtil.NowAsEpoch();
|
||||
await ct.SaveChangesAsync();
|
||||
|
||||
ct.Entry(TrialRequest).State = EntityState.Modified;
|
||||
//send approved email to user
|
||||
var body = $"Your trial license request has been approved.\r\nThe license will fetch and install automatically shortly or you can fetch it now in the License form menu.";
|
||||
//send confirmation email
|
||||
RfMail.SendMessage("support@ayanova.com", trial.Email, "AyaNova trial request approved", body, false);
|
||||
|
||||
try
|
||||
{
|
||||
await ct.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateConcurrencyException)
|
||||
{
|
||||
if (!await TrialRequestExistsAsync(id))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return Ok(trial);
|
||||
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
|
||||
//Reject
|
||||
[HttpPost("reject/{id}")]
|
||||
public async Task<IActionResult> RejectTrial([FromRoute] long id, [FromQuery] string rejectReason)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
return BadRequest(ModelState);
|
||||
var trial = await ct.TrialRequest.SingleOrDefaultAsync(m => m.Id == id);
|
||||
if (trial == null)
|
||||
return NotFound();
|
||||
//DO REJECT
|
||||
//check not already processed and ignore if so
|
||||
if(trial.DtProcessed!=null){
|
||||
//already processed, nothing to do here
|
||||
return BadRequest("Already processed");
|
||||
}
|
||||
//generate license key and insert in record
|
||||
trial.RejectReason=rejectReason;
|
||||
trial.Status = TrialRequest.TrialRequestStatus.Rejected;
|
||||
trial.DtProcessed = DateUtil.NowAsEpoch();
|
||||
await ct.SaveChangesAsync();
|
||||
|
||||
//send approved email to user
|
||||
string reason=string.Empty;
|
||||
if(!string.IsNullOrWhiteSpace(rejectReason)){
|
||||
reason=$"The request was rejected due to:\r\n{rejectReason}";
|
||||
}
|
||||
var body = $"Your trial license request was not approved.\r\n{reason}";
|
||||
//send confirmation email
|
||||
RfMail.SendMessage("support@ayanova.com", trial.Email, "AyaNova trial request approved", body, false);
|
||||
|
||||
return Ok(trial);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private async Task<bool> TrialRequestExistsAsync(long id)
|
||||
@@ -110,7 +140,7 @@ namespace rockfishCore.Controllers
|
||||
return await ct.TrialRequest.AnyAsync(e => e.Id == id);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
}//eoc
|
||||
|
||||
@@ -5,8 +5,6 @@ using System.IO;
|
||||
using Org.BouncyCastle.Security;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using rockfishCore.Models;
|
||||
using rockfishCore.Util;
|
||||
|
||||
|
||||
|
||||
@@ -30,6 +28,8 @@ namespace rockfishCore.Util
|
||||
//This feature name means it's a trial key
|
||||
private const string TRIAL_FEATURE_NAME = "TrialMode";
|
||||
|
||||
public const int TRIAL_PERIOD_DAYS = 45;
|
||||
|
||||
//This feature name means it's a SAAS or rental mode key for month to month hosted service
|
||||
private const string RENTAL_FEATURE_NAME = "ServiceMode";
|
||||
|
||||
@@ -202,6 +202,38 @@ namespace rockfishCore.Util
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
|
||||
|
||||
public static string GetRavenTrialKey(Guid dbid, string CompanyName)
|
||||
{
|
||||
|
||||
//Build a sample test key, sign it and return it
|
||||
AyaNovaLicenseKey k = new AyaNovaLicenseKey();
|
||||
k.LicenseFormat = "2018";
|
||||
|
||||
var vv = Math.Truncate((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
|
||||
string sId = vv.ToString();
|
||||
if (sId.Contains(","))
|
||||
sId = sId.Split('.')[0];
|
||||
k.Id = $"00-{sId}";
|
||||
k.RegisteredTo = CompanyName;
|
||||
k.DbId = dbid;
|
||||
|
||||
//trial period time limit
|
||||
k.MaintenanceExpiration = k.LicenseExpiration = DateTime.UtcNow.AddDays(TRIAL_PERIOD_DAYS);
|
||||
|
||||
//flag as trial key not regular key
|
||||
k.Features.Add(new LicenseFeature() { Feature = TRIAL_FEATURE_NAME, Count = 0 });
|
||||
|
||||
//add every possible feature
|
||||
k.Features.Add(new LicenseFeature() { Feature = ACCOUNTING_FEATURE_NAME, Count = 0 });
|
||||
k.Features.Add(new LicenseFeature() { Feature = SERVICE_TECHS_FEATURE_NAME, Count = 1000 });
|
||||
|
||||
return genKey(k);
|
||||
}
|
||||
|
||||
|
||||
#region RAVEN test code for development
|
||||
|
||||
//Trial key magic number for development and testing, all other guids will be fully licensed
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
/*global $, io, app */
|
||||
|
||||
app.api = (function() {
|
||||
app.api = (function () {
|
||||
"use strict";
|
||||
var initModule,
|
||||
getAuthHeaderObject,
|
||||
@@ -32,7 +32,7 @@ app.api = (function() {
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// NOT AUTHORIZED ERROR HANDLER
|
||||
|
||||
$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
|
||||
$(document).ajaxError(function (event, jqxhr, settings, thrownError) {
|
||||
//unauthorized? Trigger logout which will trigger login after clearing creds
|
||||
if (jqxhr.status == 401) {
|
||||
window.location.replace("#!/logout");
|
||||
@@ -46,7 +46,7 @@ app.api = (function() {
|
||||
// Return the auth token header
|
||||
//
|
||||
//
|
||||
getAuthHeaderObject = function() {
|
||||
getAuthHeaderObject = function () {
|
||||
return {
|
||||
Authorization: "Bearer " + app.shell.stateMap.user.token
|
||||
};
|
||||
@@ -59,7 +59,7 @@ app.api = (function() {
|
||||
//Create
|
||||
//Route app.post('/api/:obj_type/create', function (req, res) {
|
||||
//
|
||||
create = function(apiRoute, objData, callback) {
|
||||
create = function (apiRoute, objData, callback) {
|
||||
$.ajax({
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
@@ -67,10 +67,10 @@ app.api = (function() {
|
||||
headers: getAuthHeaderObject(),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
data: JSON.stringify(objData),
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -83,17 +83,17 @@ app.api = (function() {
|
||||
/////////////////
|
||||
//Get - get anything, the caller provides the route, this should replace most legacy get
|
||||
//
|
||||
get = function(apiRoute, callback) {
|
||||
get = function (apiRoute, callback) {
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
dataType: "json",
|
||||
url: app.shell.stateMap.apiUrl + apiRoute,
|
||||
headers: getAuthHeaderObject(),
|
||||
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -108,7 +108,7 @@ app.api = (function() {
|
||||
//Update
|
||||
//route: app.post('/api/:obj_type/update/:id', function (req, res) {
|
||||
//
|
||||
update = function(objType, objData, callback) {
|
||||
update = function (objType, objData, callback) {
|
||||
var theId;
|
||||
if (!objData.id) {
|
||||
return callback({
|
||||
@@ -125,14 +125,14 @@ app.api = (function() {
|
||||
headers: getAuthHeaderObject(),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
data: JSON.stringify(objData),
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
if (data == null) {
|
||||
data = { ok: 1 };
|
||||
}
|
||||
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -144,16 +144,16 @@ app.api = (function() {
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
//remove Item
|
||||
remove = function(apiRoute, callback) {
|
||||
remove = function (apiRoute, callback) {
|
||||
$.ajax({
|
||||
method: "DELETE",
|
||||
dataType: "json",
|
||||
url: app.shell.stateMap.apiUrl + apiRoute,
|
||||
headers: getAuthHeaderObject(),
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -167,7 +167,7 @@ app.api = (function() {
|
||||
// uploadFile
|
||||
// (ajax route to upload a file)
|
||||
//
|
||||
uploadFile = function(apiRoute, objData, callback) {
|
||||
uploadFile = function (apiRoute, objData, callback) {
|
||||
$.ajax({
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
@@ -176,10 +176,10 @@ app.api = (function() {
|
||||
contentType: false,
|
||||
processData: false,
|
||||
data: objData,
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -192,7 +192,7 @@ app.api = (function() {
|
||||
//////////////////////////////////////////////////////////////
|
||||
//putAction - ad-hoc put method used to trigger actions etc
|
||||
//
|
||||
putAction = function(apiRoute, callback) {
|
||||
putAction = function (apiRoute, callback) {
|
||||
$.ajax({
|
||||
method: "put",
|
||||
dataType: "json",
|
||||
@@ -200,14 +200,14 @@ app.api = (function() {
|
||||
headers: getAuthHeaderObject(),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
//data: JSON.stringify(objData),
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
if (data == null) {
|
||||
data = { ok: 1 };
|
||||
}
|
||||
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -216,6 +216,34 @@ app.api = (function() {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//postAction - ad-hoc post method used to trigger actions etc
|
||||
// (becuase it shouldn't have been put in the first place above)
|
||||
postAction = function (apiRoute, callback) {
|
||||
$.ajax({
|
||||
method: "post",
|
||||
dataType: "json",
|
||||
url: app.shell.stateMap.apiUrl + apiRoute,
|
||||
headers: getAuthHeaderObject(),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
success: function (data, textStatus) {
|
||||
if (data == null) {
|
||||
data = { ok: 1 };
|
||||
}
|
||||
|
||||
callback(data);
|
||||
},
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
error_detail: {}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// LICENSE KEY RELATED API METHODS
|
||||
|
||||
@@ -223,7 +251,7 @@ app.api = (function() {
|
||||
//CreateLicense
|
||||
//Route app.post('/api/license/create', function (req, res) {
|
||||
//
|
||||
createLicense = function(objData, callback) {
|
||||
createLicense = function (objData, callback) {
|
||||
$.ajax({
|
||||
method: "post",
|
||||
dataType: "text",
|
||||
@@ -231,10 +259,10 @@ app.api = (function() {
|
||||
headers: getAuthHeaderObject(),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
data: JSON.stringify(objData),
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -249,16 +277,16 @@ app.api = (function() {
|
||||
//Fetch license requests
|
||||
//route: app.get('/api/license/requests', function (req, res) {
|
||||
//
|
||||
getLicenseRequests = function(callback) {
|
||||
getLicenseRequests = function (callback) {
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
dataType: "json",
|
||||
url: app.shell.stateMap.apiUrl + "license/requests",
|
||||
headers: getAuthHeaderObject(),
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -273,16 +301,16 @@ app.api = (function() {
|
||||
//Fetch generated response to license request
|
||||
//route: app.get('/api/license/generateFromRequest/:uid', function (req, res) {
|
||||
//
|
||||
generateFromRequest = function(uid, callback) {
|
||||
generateFromRequest = function (uid, callback) {
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
dataType: "json",
|
||||
url: app.shell.stateMap.apiUrl + "license/generateFromRequest/" + uid,
|
||||
headers: getAuthHeaderObject(),
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -296,7 +324,7 @@ app.api = (function() {
|
||||
//Email license request response
|
||||
//app.post('/api/license/email_response', function (req, res) {
|
||||
//
|
||||
licenseEmailResponse = function(objData, callback) {
|
||||
licenseEmailResponse = function (objData, callback) {
|
||||
$.ajax({
|
||||
method: "post",
|
||||
dataType: "text",
|
||||
@@ -304,10 +332,10 @@ app.api = (function() {
|
||||
headers: getAuthHeaderObject(),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
data: JSON.stringify(objData),
|
||||
success: function(data, textStatus) {
|
||||
success: function (data, textStatus) {
|
||||
callback(data);
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
error: function (jqXHR, textStatus, errorThrown) {
|
||||
callback({
|
||||
error: 1,
|
||||
msg: textStatus + "\n" + errorThrown,
|
||||
@@ -317,7 +345,7 @@ app.api = (function() {
|
||||
});
|
||||
};
|
||||
|
||||
initModule = function() {};
|
||||
initModule = function () {};
|
||||
|
||||
return {
|
||||
initModule: initModule,
|
||||
@@ -329,6 +357,7 @@ app.api = (function() {
|
||||
update: update,
|
||||
uploadFile: uploadFile,
|
||||
putAction: putAction,
|
||||
postAction: postAction,
|
||||
createLicense: createLicense,
|
||||
getLicenseRequests: getLicenseRequests,
|
||||
generateFromRequest: generateFromRequest,
|
||||
|
||||
@@ -12,16 +12,34 @@ app.trialEdit = (function () {
|
||||
//---------------- BEGIN MODULE SCOPE VARIABLES --------------
|
||||
var
|
||||
stateMap = {},
|
||||
onSave, onDelete,
|
||||
onApprove, onReject, onDelete,
|
||||
configModule, initModule;
|
||||
//----------------- END MODULE SCOPE VARIABLES ---------------
|
||||
|
||||
|
||||
//------------------- BEGIN EVENT HANDLERS -------------------
|
||||
|
||||
//ONSAVE
|
||||
//ONAPPROVE
|
||||
//
|
||||
onSave = function (event) {
|
||||
onApprove = function (event) {
|
||||
event.preventDefault();
|
||||
$.gevent.publish('app-clear-error');
|
||||
|
||||
var isFetched=$('#fetched').prop('checked')
|
||||
|
||||
|
||||
app.api.postAction('trial/fetched/' + stateMap.id + "/" + isFetched, function (res) {
|
||||
if (res.error) {
|
||||
$.gevent.publish('app-show-error', res.msg);
|
||||
}
|
||||
});
|
||||
|
||||
return false; //prevent default?
|
||||
};
|
||||
|
||||
//ONREJECT
|
||||
//
|
||||
onReject = function (event) {
|
||||
event.preventDefault();
|
||||
$.gevent.publish('app-clear-error');
|
||||
|
||||
@@ -37,6 +55,7 @@ app.trialEdit = (function () {
|
||||
return false; //prevent default?
|
||||
};
|
||||
|
||||
|
||||
//ONDELETE
|
||||
//
|
||||
onDelete = function (event) {
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="rejectReason">Reject reason</label>
|
||||
<label for="rejectReason">Reject reason *emailed to user</label>
|
||||
<input class="form-control" type="text" id="rejectReason" name="rejectReason" value="" >
|
||||
</div>
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user