add ability to register for updates

This commit is contained in:
Shaun Walker 2021-06-27 08:48:18 -04:00
parent db1808d3e9
commit 9e004f5b3c
13 changed files with 136 additions and 39 deletions

View File

@ -101,6 +101,11 @@
</div> </div>
<div class="app-progress-indicator" style="@_loadingDisplay"></div> <div class="app-progress-indicator" style="@_loadingDisplay"></div>
</div> </div>
<div class="row">
<div class="mx-auto text-center">
<input type="checkbox" @bind="@_register" /> @Localizer["Register"]
</div>
</div>
</div> </div>
@code { @code {
@ -114,6 +119,7 @@
private string _hostPassword = string.Empty; private string _hostPassword = string.Empty;
private string _confirmPassword = string.Empty; private string _confirmPassword = string.Empty;
private string _hostEmail = string.Empty; private string _hostEmail = string.Empty;
private bool _register = true;
private string _message = string.Empty; private string _message = string.Empty;
private string _loadingDisplay = "display: none;"; private string _loadingDisplay = "display: none;";
@ -169,7 +175,7 @@
connectionString = databaseConfigControl.GetConnectionString(); connectionString = databaseConfigControl.GetConnectionString();
} }
if (connectionString != "" && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "") if (connectionString != "" && _hostUsername != "" && _hostPassword.Length >= 6 && _hostPassword == _confirmPassword && _hostEmail != "" && _hostEmail.Contains("@"))
{ {
_loadingDisplay = ""; _loadingDisplay = "";
StateHasChanged(); StateHasChanged();
@ -188,7 +194,8 @@
HostName = UserNames.Host, HostName = UserNames.Host,
TenantName = TenantNames.Master, TenantName = TenantNames.Master,
IsNewTenant = true, IsNewTenant = true,
SiteName = Constants.DefaultSite SiteName = Constants.DefaultSite,
Register = _register
}; };
var installation = await InstallationService.Install(config); var installation = await InstallationService.Install(config);

View File

@ -56,6 +56,12 @@
</td> </td>
</tr> </tr>
</table> </table>
<div class="row">
<div class="mx-auto text-center">
<input type="checkbox" @onchange="(e => RegisterChecked(e))" /> @Localizer["Register"]
</div>
</div>
<br /><br />
<a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Access.ApiFramework"]</a>&nbsp; <a class="btn btn-primary" href="swagger/index.html" target="_new">@Localizer["Access.ApiFramework"]</a>&nbsp;
<ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" /> <ActionDialog Header="Restart Application" Message="Are You Sure You Wish To Restart The Application?" Action="Restart Application" Security="SecurityAccessLevel.Host" Class="btn btn-danger" OnClick="@(async () => await RestartApplication())" ResourceKey="RestartApplication" />
</TabPanel> </TabPanel>
@ -183,4 +189,20 @@
await logger.LogError(ex, "Error Restarting Application"); await logger.LogError(ex, "Error Restarting Application");
} }
} }
private async Task RegisterChecked(ChangeEventArgs e)
{
try
{
if ((bool)e.Value)
{
await InstallationService.RegisterAsync(PageState.User.Email);
AddModuleMessage(Localizer["Success.Register"], MessageType.Success);
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error On Register");
}
}
} }

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
@ -148,6 +148,9 @@
<value>Error loading Database Configuration Control</value> <value>Error loading Database Configuration Control</value>
</data> </data>
<data name="Message.Require.DbInfo" xml:space="preserve"> <data name="Message.Require.DbInfo" xml:space="preserve">
<value>Please Enter All Fields And Ensure Passwords Match And Are Greater Than 5 Characters In Length</value> <value>Please Enter All Required Fields. Ensure Passwords Match And Are Greater Than 5 Characters In Length. Ensure Email Address Provided Is Valid.</value>
</data>
<data name="Register" xml:space="preserve">
<value>Please Register Me For Major Product Updates And Security Bulletins</value>
</data> </data>
</root> </root>

View File

@ -204,16 +204,16 @@
<data name="LoggingLevel.HelpText" xml:space="preserve"> <data name="LoggingLevel.HelpText" xml:space="preserve">
<value>The Minimum Logging Level For The Event Log. This Option Can Be Used To Control The Volume Of Items Stored In Your Event Log.</value> <value>The Minimum Logging Level For The Event Log. This Option Can Be Used To Control The Volume Of Items Stored In Your Event Log.</value>
</data> </data>
<data name="Trace" xml:space="preserve"> <data name="Trace" xml:space="preserve">
<value>Trace</value> <value>Trace</value>
</data> </data>
<data name="Debug" xml:space="preserve"> <data name="Debug" xml:space="preserve">
<value>Debug</value> <value>Debug</value>
</data> </data>
<data name="Information" xml:space="preserve"> <data name="Information" xml:space="preserve">
<value>Information</value> <value>Information</value>
</data> </data>
<data name="Warning" xml:space="preserve"> <data name="Warning" xml:space="preserve">
<value>Warning</value> <value>Warning</value>
</data> </data>
<data name="Error" xml:space="preserve"> <data name="Error" xml:space="preserve">
@ -228,4 +228,10 @@
<data name="Options" xml:space="preserve"> <data name="Options" xml:space="preserve">
<value>Options</value> <value>Options</value>
</data> </data>
<data name="Register" xml:space="preserve">
<value>Please Register Me For Major Product Updates And Security Bulletins</value>
</data>
<data name="Success.Register" xml:space="preserve">
<value>You Have Been Successfully Registered For Updates</value>
</data>
</root> </root>

View File

@ -45,5 +45,10 @@ namespace Oqtane.Services
{ {
await PostAsync($"{ApiUrl}/restart"); await PostAsync($"{ApiUrl}/restart");
} }
public async Task RegisterAsync(string email)
{
await PostAsync($"{ApiUrl}/register?email={WebUtility.UrlEncode(email)}");
}
} }
} }

View File

@ -10,5 +10,6 @@ namespace Oqtane.Services
Task<Installation> Install(InstallConfig config); Task<Installation> Install(InstallConfig config);
Task<Installation> Upgrade(); Task<Installation> Upgrade();
Task RestartAsync(); Task RestartAsync();
Task RegisterAsync(string email);
} }
} }

View File

@ -5,7 +5,6 @@ using System.Linq;
using System.IO.Compression; using System.IO.Compression;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Oqtane.Infrastructure; using Oqtane.Infrastructure;
using Oqtane.Models; using Oqtane.Models;
using Oqtane.Modules; using Oqtane.Modules;
@ -16,13 +15,15 @@ using System.Net;
using Oqtane.Repository; using Oqtane.Repository;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using System.Diagnostics; using System.Diagnostics;
using System.Net.Http;
using System.Net.Http.Headers;
namespace Oqtane.Controllers namespace Oqtane.Controllers
{ {
[Route(ControllerRoutes.ApiRoute)] [Route(ControllerRoutes.ApiRoute)]
public class InstallationController : Controller public class InstallationController : Controller
{ {
private readonly IConfigurationRoot _config; private readonly IConfigManager _configManager;
private readonly IInstallationManager _installationManager; private readonly IInstallationManager _installationManager;
private readonly IDatabaseManager _databaseManager; private readonly IDatabaseManager _databaseManager;
private readonly ILocalizationManager _localizationManager; private readonly ILocalizationManager _localizationManager;
@ -30,9 +31,9 @@ namespace Oqtane.Controllers
private readonly IHttpContextAccessor _accessor; private readonly IHttpContextAccessor _accessor;
private readonly IAliasRepository _aliases; private readonly IAliasRepository _aliases;
public InstallationController(IConfigurationRoot config, IInstallationManager installationManager, IDatabaseManager databaseManager, ILocalizationManager localizationManager, IMemoryCache cache, IHttpContextAccessor accessor, IAliasRepository aliases) public InstallationController(IConfigManager configManager, IInstallationManager installationManager, IDatabaseManager databaseManager, ILocalizationManager localizationManager, IMemoryCache cache, IHttpContextAccessor accessor, IAliasRepository aliases)
{ {
_config = config; _configManager = configManager;
_installationManager = installationManager; _installationManager = installationManager;
_databaseManager = databaseManager; _databaseManager = databaseManager;
_localizationManager = localizationManager; _localizationManager = localizationManager;
@ -47,9 +48,14 @@ namespace Oqtane.Controllers
{ {
var installation = new Installation {Success = false, Message = ""}; var installation = new Installation {Success = false, Message = ""};
if (ModelState.IsValid && (User.IsInRole(RoleNames.Host) || string.IsNullOrEmpty(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))) if (ModelState.IsValid && (User.IsInRole(RoleNames.Host) || string.IsNullOrEmpty(_configManager.GetSetting("ConnectionStrings:" + SettingKeys.ConnectionStringKey, ""))))
{ {
installation = _databaseManager.Install(config); installation = _databaseManager.Install(config);
if (config.Register)
{
RegisterContact(config.HostEmail);
}
} }
else else
{ {
@ -93,7 +99,7 @@ namespace Oqtane.Controllers
[HttpGet("load")] [HttpGet("load")]
public IActionResult Load() public IActionResult Load()
{ {
if (_config.GetSection("Runtime").Value == "WebAssembly") if (_configManager.GetSection("Runtime").Value == "WebAssembly")
{ {
return File(GetAssemblies(), System.Net.Mime.MediaTypeNames.Application.Octet, "oqtane.dll"); return File(GetAssemblies(), System.Net.Mime.MediaTypeNames.Application.Octet, "oqtane.dll");
} }
@ -199,5 +205,30 @@ namespace Oqtane.Controllers
} }
}); });
} }
private void RegisterContact(string email)
{
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value);
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version));
client.GetAsync(Constants.PackageRegistryUrl + $"/api/registry/contact/?id={_configManager.GetInstallationId()}&email={WebUtility.UrlEncode(email)}");
}
}
catch
{
// error calling registry service
}
}
// GET api/<controller>/register?email=x
[HttpPost("register")]
[Authorize(Roles = RoleNames.Host)]
public void Register(string email)
{
RegisterContact(email);
}
} }
} }

View File

@ -42,7 +42,7 @@ namespace Oqtane.Controllers
{ {
client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value); client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value);
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version)); client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version));
packages = await GetJson<List<Package>>(client, Constants.PackageRegistryUrl + $"/api/registry/packages/?id={GetInstallationId()}&type={type.ToLower()}&version={Constants.Version}&search={search}"); packages = await GetJson<List<Package>>(client, Constants.PackageRegistryUrl + $"/api/registry/packages/?id={_configManager.GetInstallationId()}&type={type.ToLower()}&version={Constants.Version}&search={search}");
} }
return packages; return packages;
} }
@ -57,7 +57,7 @@ namespace Oqtane.Controllers
{ {
client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value); client.DefaultRequestHeaders.Add("Referer", HttpContext.Request.Scheme + "://" + HttpContext.Request.Host.Value);
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version)); client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.PackageId, Constants.Version));
package = await GetJson<Package>(client, Constants.PackageRegistryUrl + $"/api/registry/package/?id={GetInstallationId()}&package={packageid}&version={version}"); package = await GetJson<Package>(client, Constants.PackageRegistryUrl + $"/api/registry/package/?id={_configManager.GetInstallationId()}&package={packageid}&version={version}");
} }
if (package != null) if (package != null)
@ -86,17 +86,6 @@ namespace Oqtane.Controllers
} }
} }
private string GetInstallationId()
{
var installationid = _configManager.GetSetting("InstallationId", "");
if (installationid == "")
{
installationid = Guid.NewGuid().ToString();
_configManager.AddOrUpdateSetting("InstallationId", installationid, true);
}
return installationid;
}
private async Task<T> GetJson<T>(HttpClient httpClient, string url) private async Task<T> GetJson<T>(HttpClient httpClient, string url)
{ {
Uri uri = new Uri(url); Uri uri = new Uri(url);

View File

@ -32,7 +32,7 @@ namespace Oqtane.Controllers
systeminfo.Add("machinename", Environment.MachineName); systeminfo.Add("machinename", Environment.MachineName);
systeminfo.Add("serverpath", _environment.ContentRootPath); systeminfo.Add("serverpath", _environment.ContentRootPath);
systeminfo.Add("servertime", DateTime.Now.ToString()); systeminfo.Add("servertime", DateTime.Now.ToString());
systeminfo.Add("installationid", GetInstallationId()); systeminfo.Add("installationid", _configManager.GetInstallationId());
systeminfo.Add("runtime", _configManager.GetSetting("Runtime", "Server")); systeminfo.Add("runtime", _configManager.GetSetting("Runtime", "Server"));
systeminfo.Add("rendermode", _configManager.GetSetting("RenderMode", "ServerPrerendered")); systeminfo.Add("rendermode", _configManager.GetSetting("RenderMode", "ServerPrerendered"));
@ -65,16 +65,5 @@ namespace Oqtane.Controllers
} }
} }
} }
private string GetInstallationId()
{
var installationid = _configManager.GetSetting("InstallationId", "");
if (installationid == "")
{
installationid = Guid.NewGuid().ToString();
_configManager.AddOrUpdateSetting("InstallationId", installationid, true);
}
return installationid;
}
} }
} }

View File

@ -4,6 +4,7 @@ using System.IO;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Oqtane.Shared;
namespace Oqtane.Infrastructure namespace Oqtane.Infrastructure
{ {
@ -115,5 +116,31 @@ namespace Oqtane.Infrastructure
{ {
_config.Reload(); _config.Reload();
} }
public string GetConnectionString()
{
return _config.GetConnectionString(SettingKeys.ConnectionStringKey);
}
public string GetConnectionString(string name)
{
return _config.GetConnectionString(name);
}
public bool IsInstalled()
{
return !string.IsNullOrEmpty(GetConnectionString());
}
public string GetInstallationId()
{
var installationid = GetSetting("InstallationId", "");
if (installationid == "")
{
installationid = Guid.NewGuid().ToString();
AddOrUpdateSetting("InstallationId", installationid, true);
}
return installationid;
}
} }
} }

View File

@ -12,5 +12,10 @@ namespace Oqtane.Infrastructure
void RemoveSetting(string key, bool reload); void RemoveSetting(string key, bool reload);
void RemoveSetting(string file, string key, bool reload); void RemoveSetting(string file, string key, bool reload);
void Reload(); void Reload();
public string GetConnectionString();
public string GetConnectionString(string name);
public bool IsInstalled();
public string GetInstallationId();
} }
} }

View File

@ -143,6 +143,17 @@ namespace Oqtane.Migrations.EntityBuilders
unique: isUnique); unique: isUnique);
} }
public virtual void AddForeignKey(string foreignKeyName, string columnName, string principalTable, string principalColumn, ReferentialAction onDelete)
{
_migrationBuilder.AddForeignKey(
name: RewriteName(foreignKeyName),
table: RewriteName(EntityTableName),
column: RewriteName(columnName),
principalTable: RewriteName(principalTable),
principalColumn: RewriteName(principalColumn),
onDelete: onDelete );
}
/// <summary> /// <summary>
/// Creates a Migration to add an Index to the Entity (table) /// Creates a Migration to add an Index to the Entity (table)
/// </summary> /// </summary>

View File

@ -16,5 +16,6 @@ namespace Oqtane.Shared
public string DefaultTheme { get; set; } public string DefaultTheme { get; set; }
public string DefaultContainer { get; set; } public string DefaultContainer { get; set; }
public string DefaultAdminContainer { get; set; } public string DefaultAdminContainer { get; set; }
public bool Register { get; set; }
} }
} }