added support for default alias specification, alias auto registration, alias redirect, alias line break delimiters
This commit is contained in:
		@ -1,5 +1,6 @@
 | 
			
		||||
@namespace Oqtane.Modules.Admin.Site
 | 
			
		||||
@inherits ModuleBase
 | 
			
		||||
@using System.Text.RegularExpressions
 | 
			
		||||
@inject NavigationManager NavigationManager
 | 
			
		||||
@inject ISiteService SiteService
 | 
			
		||||
@inject ITenantService TenantService
 | 
			
		||||
@ -22,81 +23,64 @@
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="row mb-1 align-items-center">
 | 
			
		||||
                <Label Class="col-sm-3" For="alias" HelpText="The aliases for the site. An alias can be a domain name (www.site.com) or a virtual folder (ie. www.site.com/folder). If a site has multiple aliases they should be separated by commas." ResourceKey="Aliases">Aliases: </Label>
 | 
			
		||||
                <Label Class="col-sm-3" For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
 | 
			
		||||
                <div class="col-sm-9">
 | 
			
		||||
                    @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
 | 
			
		||||
                    {
 | 
			
		||||
                        <textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        <textarea id="alias" class="form-control" @bind="@_urls" rows="3" readonly></textarea>
 | 
			
		||||
                    }
 | 
			
		||||
                    <FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="row mb-1 align-items-center">
 | 
			
		||||
                <Label Class="col-sm-3" For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Is Deleted? </Label>
 | 
			
		||||
                <Label Class="col-sm-3" For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
 | 
			
		||||
                <div class="col-sm-9">
 | 
			
		||||
                    <select id="isDeleted" class="form-select" @bind="@_isdeleted" required>
 | 
			
		||||
                        <option value="True">@SharedLocalizer["Yes"]</option>
 | 
			
		||||
                        <option value="False">@SharedLocalizer["No"]</option>
 | 
			
		||||
                    <FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="row mb-1 align-items-center">
 | 
			
		||||
                <Label Class="col-sm-3" For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
 | 
			
		||||
                <div class="col-sm-9">
 | 
			
		||||
                    <select id="defaultTheme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
 | 
			
		||||
                        <option value="-"><@Localizer["Theme.Select"]></option>
 | 
			
		||||
                        @foreach (var theme in _themes)
 | 
			
		||||
                        {
 | 
			
		||||
                            <option value="@theme.TypeName">@theme.Name</option>
 | 
			
		||||
                        }
 | 
			
		||||
                    </select>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <Section Name="Appearance" Heading="Appearance" ResourceKey="Appearance">
 | 
			
		||||
            <div class="container">
 | 
			
		||||
                <div class="row mb-1 align-items-center">
 | 
			
		||||
                    <Label Class="col-sm-3" For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
 | 
			
		||||
                    <div class="col-sm-9">
 | 
			
		||||
                        <FileManager FileId="@_logofileid" Filter="@Constants.ImageFiles" @ref="_logofilemanager" />
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="row mb-1 align-items-center">
 | 
			
		||||
                    <Label Class="col-sm-3" For="favicon" HelpText="Specify a Favicon" ResourceKey="FavoriteIcon">Favicon: </Label>
 | 
			
		||||
                    <div class="col-sm-9">
 | 
			
		||||
                        <FileManager FileId="@_faviconfileid" Filter="ico" @ref="_faviconfilemanager" />
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="row mb-1 align-items-center">
 | 
			
		||||
                    <Label Class="col-sm-3" For="defaultTheme" HelpText="Select the sites default theme" ResourceKey="DefaultTheme">Default Theme: </Label>
 | 
			
		||||
                    <div class="col-sm-9">
 | 
			
		||||
                        <select id="defaultTheme" class="form-select" value="@_themetype" @onchange="(e => ThemeChanged(e))" required>
 | 
			
		||||
                            <option value="-"><@Localizer["Theme.Select"]></option>
 | 
			
		||||
                            @foreach (var theme in _themes)
 | 
			
		||||
                            {
 | 
			
		||||
                                <option value="@theme.TypeName">@theme.Name</option>
 | 
			
		||||
                            }
 | 
			
		||||
                        </select>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="row mb-1 align-items-center">
 | 
			
		||||
                    <Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
 | 
			
		||||
                    <div class="col-sm-9">
 | 
			
		||||
                        <select id="defaultContainer" class="form-select" @bind="@_containertype" required>
 | 
			
		||||
                            <option value="-"><@Localizer["Container.Select"]></option>
 | 
			
		||||
                            @foreach (var container in _containers)
 | 
			
		||||
                            {
 | 
			
		||||
                                <option value="@container.TypeName">@container.Name</option>
 | 
			
		||||
                            }
 | 
			
		||||
                        </select>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="row mb-1 align-items-center">
 | 
			
		||||
                    <Label Class="col-sm-3" For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
 | 
			
		||||
                    <div class="col-sm-9">
 | 
			
		||||
                        <select id="defaultAdminContainer" class="form-select" @bind="@_admincontainertype" required>
 | 
			
		||||
                            <option value="-"><@Localizer["Container.Select"]></option>
 | 
			
		||||
                            <option value="@Constants.DefaultAdminContainer"><@Localizer["DefaultAdminContainer"]></option>
 | 
			
		||||
                            @foreach (var container in _containers)
 | 
			
		||||
                            {
 | 
			
		||||
                                <option value="@container.TypeName">@container.Name</option>
 | 
			
		||||
                            }
 | 
			
		||||
                        </select>
 | 
			
		||||
                    </div>
 | 
			
		||||
            <div class="row mb-1 align-items-center">
 | 
			
		||||
                <Label Class="col-sm-3" For="defaultContainer" HelpText="Select the default container for the site" ResourceKey="DefaultContainer">Default Container: </Label>
 | 
			
		||||
                <div class="col-sm-9">
 | 
			
		||||
                    <select id="defaultContainer" class="form-select" @bind="@_containertype" required>
 | 
			
		||||
                        <option value="-"><@Localizer["Container.Select"]></option>
 | 
			
		||||
                        @foreach (var container in _containers)
 | 
			
		||||
                        {
 | 
			
		||||
                            <option value="@container.TypeName">@container.Name</option>
 | 
			
		||||
                        }
 | 
			
		||||
                    </select>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </Section>
 | 
			
		||||
            <div class="row mb-1 align-items-center">
 | 
			
		||||
                <Label Class="col-sm-3" For="defaultAdminContainer" HelpText="Select the default admin container for the site" ResourceKey="DefaultAdminContainer">Default Admin Container: </Label>
 | 
			
		||||
                <div class="col-sm-9">
 | 
			
		||||
                    <select id="defaultAdminContainer" class="form-select" @bind="@_admincontainertype" required>
 | 
			
		||||
                        <option value="-"><@Localizer["Container.Select"]></option>
 | 
			
		||||
                        <option value="@Constants.DefaultAdminContainer"><@Localizer["DefaultAdminContainer"]></option>
 | 
			
		||||
                        @foreach (var container in _containers)
 | 
			
		||||
                        {
 | 
			
		||||
                            <option value="@container.TypeName">@container.Name</option>
 | 
			
		||||
                        }
 | 
			
		||||
                    </select>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
			<div class="row mb-1 align-items-center">
 | 
			
		||||
				<Label Class="col-sm-3" For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Deleted? </Label>
 | 
			
		||||
				<div class="col-sm-9">
 | 
			
		||||
					<select id="isDeleted" class="form-select" @bind="@_isdeleted" required>
 | 
			
		||||
						<option value="True">@SharedLocalizer["Yes"]</option>
 | 
			
		||||
						<option value="False">@SharedLocalizer["No"]</option>
 | 
			
		||||
					</select>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
        <Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
 | 
			
		||||
            <div class="container">
 | 
			
		||||
                <div class="row mb-1 align-items-center">
 | 
			
		||||
@ -176,6 +160,27 @@
 | 
			
		||||
        </Section>
 | 
			
		||||
        @if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
 | 
			
		||||
        {
 | 
			
		||||
			<Section Name="Aliases" Heading="Aliases" ResourceKey="Aliases">
 | 
			
		||||
                <div class="container">
 | 
			
		||||
					<div class="row mb-1 align-items-center">
 | 
			
		||||
						<Label Class="col-sm-3" For="alias" HelpText="The aliases for the site. An alias can be a domain name (www.site.com) or a virtual folder (ie. www.site.com/folder). If a site has multiple aliases they should be separated by commas." ResourceKey="Aliases">Aliases: </Label>
 | 
			
		||||
						<div class="col-sm-9">
 | 
			
		||||
							<textarea id="alias" class="form-control" @bind="@_urls" rows="3" required></textarea>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
					<div class="row mb-1 align-items-center">
 | 
			
		||||
						<Label Class="col-sm-3" For="defaultalias" HelpText="The default alias for the site. Requests for non-default aliases will be redirected to the default alias." ResourceKey="DefaultAlias">Default Alias: </Label>
 | 
			
		||||
						<div class="col-sm-9">
 | 
			
		||||
                            <select id="defaultalias" class="form-select" @bind="@_defaultalias" required>
 | 
			
		||||
								@foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
 | 
			
		||||
								{
 | 
			
		||||
									<option value="@name">@name</option>
 | 
			
		||||
								}
 | 
			
		||||
                            </select>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</Section>
 | 
			
		||||
            <Section Name="Hosting" Heading="Hosting Model" ResourceKey="Hosting">
 | 
			
		||||
                <div class="container">
 | 
			
		||||
                    <div class="row mb-1 align-items-center">
 | 
			
		||||
@ -238,7 +243,8 @@
 | 
			
		||||
	private List<ThemeControl> _themes = new List<ThemeControl>();
 | 
			
		||||
	private List<ThemeControl> _containers = new List<ThemeControl>();
 | 
			
		||||
	private string _name = string.Empty;
 | 
			
		||||
	private List<Alias> _aliasList;
 | 
			
		||||
	private List<Alias> _aliases;
 | 
			
		||||
	private string _defaultalias = string.Empty;
 | 
			
		||||
	private string _urls = string.Empty;
 | 
			
		||||
	private string _runtime = "";
 | 
			
		||||
	private string _prerender = "";
 | 
			
		||||
@ -288,13 +294,7 @@
 | 
			
		||||
 | 
			
		||||
				if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
 | 
			
		||||
				{
 | 
			
		||||
					_aliasList = await AliasService.GetAliasesAsync();
 | 
			
		||||
					foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
 | 
			
		||||
					{
 | 
			
		||||
						_urls += alias.Name + ",";
 | 
			
		||||
					}
 | 
			
		||||
					_urls = _urls.Substring(0, _urls.Length - 1);
 | 
			
		||||
 | 
			
		||||
					await GetAliases();
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (site.LogoFileId != null)
 | 
			
		||||
@ -322,7 +322,7 @@
 | 
			
		||||
				{
 | 
			
		||||
					_pwasplashiconfileid = site.PwaSplashIconFileId.Value;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
 | 
			
		||||
				var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
 | 
			
		||||
				_smtphost = SettingService.GetSetting(settings, "SMTPHost", string.Empty);
 | 
			
		||||
				_smtpport = SettingService.GetSetting(settings, "SMTPPort", string.Empty);
 | 
			
		||||
@ -395,14 +395,16 @@
 | 
			
		||||
			{
 | 
			
		||||
				if (_name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-")
 | 
			
		||||
				{
 | 
			
		||||
					_urls = Regex.Replace(_urls, @"\r\n?|\n", ","); // convert line breaks to commas
 | 
			
		||||
					var unique = true;
 | 
			
		||||
					if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
 | 
			
		||||
					{
 | 
			
		||||
						foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
 | 
			
		||||
						foreach (string name in _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray())
 | 
			
		||||
						{
 | 
			
		||||
							if (_aliasList.Exists(item => item.Name == name && item.SiteId != PageState.Alias.SiteId && item.TenantId != PageState.Alias.TenantId))
 | 
			
		||||
							var alias = _aliases.Where(item => item.Name == name).FirstOrDefault();
 | 
			
		||||
							if (alias != null && unique)
 | 
			
		||||
							{
 | 
			
		||||
								unique = false;
 | 
			
		||||
								unique = (alias.TenantId == PageState.Site.TenantId && alias.SiteId == PageState.Site.SiteId);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
@ -461,145 +463,173 @@
 | 
			
		||||
							int? pwaappiconfileid = _pwaappiconfilemanager.GetFileId();
 | 
			
		||||
							if (pwaappiconfileid == -1) pwaappiconfileid = null;
 | 
			
		||||
							if (site.PwaAppIconFileId != pwaappiconfileid)
 | 
			
		||||
                            {
 | 
			
		||||
                                site.PwaAppIconFileId = pwaappiconfileid;
 | 
			
		||||
							{
 | 
			
		||||
								site.PwaAppIconFileId = pwaappiconfileid;
 | 
			
		||||
								reload = true; // needs to be reloaded on server
 | 
			
		||||
                            }
 | 
			
		||||
                            int? pwasplashiconfileid = _pwasplashiconfilemanager.GetFileId();
 | 
			
		||||
							}
 | 
			
		||||
							int? pwasplashiconfileid = _pwasplashiconfilemanager.GetFileId();
 | 
			
		||||
							if (pwasplashiconfileid == -1) pwasplashiconfileid = null;
 | 
			
		||||
                            if (site.PwaSplashIconFileId != pwasplashiconfileid)
 | 
			
		||||
                            {
 | 
			
		||||
                                site.PwaSplashIconFileId = pwasplashiconfileid;
 | 
			
		||||
							if (site.PwaSplashIconFileId != pwasplashiconfileid)
 | 
			
		||||
							{
 | 
			
		||||
								site.PwaSplashIconFileId = pwasplashiconfileid;
 | 
			
		||||
								reload = true; // needs to be reloaded on server
 | 
			
		||||
                            }
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
                            site = await SiteService.UpdateSiteAsync(site);
 | 
			
		||||
							site = await SiteService.UpdateSiteAsync(site);
 | 
			
		||||
 | 
			
		||||
                            var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
 | 
			
		||||
                            SettingService.SetSetting(settings, "SMTPHost", _smtphost, false);
 | 
			
		||||
                            SettingService.SetSetting(settings, "SMTPPort", _smtpport, false);
 | 
			
		||||
                            SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, false);
 | 
			
		||||
                            SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, false);
 | 
			
		||||
                            SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, false);
 | 
			
		||||
                            SettingService.SetSetting(settings, "SMTPSender", _smtpsender, false);
 | 
			
		||||
                            await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
 | 
			
		||||
							var settings = await SettingService.GetSiteSettingsAsync(site.SiteId);
 | 
			
		||||
							SettingService.SetSetting(settings, "SMTPHost", _smtphost, false);
 | 
			
		||||
							SettingService.SetSetting(settings, "SMTPPort", _smtpport, false);
 | 
			
		||||
							SettingService.SetSetting(settings, "SMTPSSL", _smtpssl, false);
 | 
			
		||||
							SettingService.SetSetting(settings, "SMTPUsername", _smtpusername, false);
 | 
			
		||||
							SettingService.SetSetting(settings, "SMTPPassword", _smtppassword, false);
 | 
			
		||||
							SettingService.SetSetting(settings, "SMTPSender", _smtpsender, false);
 | 
			
		||||
							await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
 | 
			
		||||
 | 
			
		||||
                            if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
 | 
			
		||||
                            {
 | 
			
		||||
                                var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
 | 
			
		||||
                                foreach (Alias alias in _aliasList.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (!names.Contains(alias.Name))
 | 
			
		||||
                                    {
 | 
			
		||||
                                        await AliasService.DeleteAliasAsync(alias.AliasId);
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
							if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
 | 
			
		||||
							{
 | 
			
		||||
								var names = _urls.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
 | 
			
		||||
									.Select(sValue => sValue.Trim()).ToArray();
 | 
			
		||||
								foreach (Alias alias in _aliases.Where(item => item.SiteId == site.SiteId && item.TenantId == site.TenantId).ToList())
 | 
			
		||||
								{
 | 
			
		||||
									if (!names.Contains(alias.Name))
 | 
			
		||||
									{
 | 
			
		||||
										await AliasService.DeleteAliasAsync(alias.AliasId);
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
								if (!names.Contains(_defaultalias)) { _defaultalias = names[0]; }
 | 
			
		||||
 | 
			
		||||
                                foreach (string name in names)
 | 
			
		||||
                                {
 | 
			
		||||
                                    if (!_aliasList.Exists(item => item.Name == name))
 | 
			
		||||
                                    {
 | 
			
		||||
                                        Alias alias = new Alias();
 | 
			
		||||
                                        alias.Name = name;
 | 
			
		||||
                                        alias.TenantId = site.TenantId;
 | 
			
		||||
                                        alias.SiteId = site.SiteId;
 | 
			
		||||
                                        await AliasService.AddAliasAsync(alias);
 | 
			
		||||
                                    }
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
								foreach (string name in names)
 | 
			
		||||
								{
 | 
			
		||||
									var alias = _aliases.Find(item => item.Name == name);
 | 
			
		||||
									if (alias == null)
 | 
			
		||||
									{
 | 
			
		||||
										alias = new Alias();
 | 
			
		||||
										alias.Name = name;
 | 
			
		||||
										alias.TenantId = site.TenantId;
 | 
			
		||||
										alias.SiteId = site.SiteId;
 | 
			
		||||
										alias.IsDefault = (name == _defaultalias);
 | 
			
		||||
										await AliasService.AddAliasAsync(alias);
 | 
			
		||||
									}
 | 
			
		||||
									else
 | 
			
		||||
									{
 | 
			
		||||
										if (alias.IsDefault != (alias.Name == _defaultalias))
 | 
			
		||||
										{
 | 
			
		||||
											alias.IsDefault = (name == _defaultalias);
 | 
			
		||||
											await AliasService.UpdateAliasAsync(alias);
 | 
			
		||||
										}
 | 
			
		||||
									}
 | 
			
		||||
								}
 | 
			
		||||
								await GetAliases();
 | 
			
		||||
							}
 | 
			
		||||
 | 
			
		||||
                            await logger.LogInformation("Site Settings Saved {Site}", site);
 | 
			
		||||
							await logger.LogInformation("Site Settings Saved {Site}", site);
 | 
			
		||||
 | 
			
		||||
                            if (refresh)
 | 
			
		||||
                            {
 | 
			
		||||
                                NavigationManager.NavigateTo(NavigateUrl(true), reload); // refresh/reload
 | 
			
		||||
                            }
 | 
			
		||||
                            else
 | 
			
		||||
                            {
 | 
			
		||||
                                AddModuleMessage(Localizer["Success.Settings.SaveSite"], MessageType.Success);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                    {
 | 
			
		||||
                        AddModuleMessage(Localizer["Message.Aliases.Taken"], MessageType.Warning);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    AddModuleMessage(Localizer["Message.Required.SiteName"], MessageType.Warning);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                await logger.LogError(ex, "Error Saving Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
 | 
			
		||||
                AddModuleMessage(Localizer["Error.SaveSite"], MessageType.Error);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
							if (refresh)
 | 
			
		||||
							{
 | 
			
		||||
								NavigationManager.NavigateTo(NavigateUrl(true), reload); // refresh/reload
 | 
			
		||||
							}
 | 
			
		||||
							else
 | 
			
		||||
							{
 | 
			
		||||
								AddModuleMessage(Localizer["Success.Settings.SaveSite"], MessageType.Success);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						AddModuleMessage(Localizer["Message.Aliases.Taken"], MessageType.Warning);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					AddModuleMessage(Localizer["Message.Required.SiteName"], MessageType.Warning);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception ex)
 | 
			
		||||
			{
 | 
			
		||||
				await logger.LogError(ex, "Error Saving Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
 | 
			
		||||
				AddModuleMessage(Localizer["Error.SaveSite"], MessageType.Error);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    private async Task DeleteSite()
 | 
			
		||||
    {
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            var sites = await SiteService.GetSitesAsync();
 | 
			
		||||
            if (sites.Count > 1)
 | 
			
		||||
            {
 | 
			
		||||
                await SiteService.DeleteSiteAsync(PageState.Site.SiteId);
 | 
			
		||||
                await logger.LogInformation("Site Deleted {SiteId}", PageState.Site.SiteId);
 | 
			
		||||
	private async Task DeleteSite()
 | 
			
		||||
	{
 | 
			
		||||
		try
 | 
			
		||||
		{
 | 
			
		||||
			var sites = await SiteService.GetSitesAsync();
 | 
			
		||||
			if (sites.Count > 1)
 | 
			
		||||
			{
 | 
			
		||||
				await SiteService.DeleteSiteAsync(PageState.Site.SiteId);
 | 
			
		||||
				await logger.LogInformation("Site Deleted {SiteId}", PageState.Site.SiteId);
 | 
			
		||||
 | 
			
		||||
                var aliases = await AliasService.GetAliasesAsync();
 | 
			
		||||
                foreach (Alias a in aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId))
 | 
			
		||||
                {
 | 
			
		||||
                    await AliasService.DeleteAliasAsync(a.AliasId);
 | 
			
		||||
                }
 | 
			
		||||
				var aliases = await AliasService.GetAliasesAsync();
 | 
			
		||||
				foreach (Alias a in aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId))
 | 
			
		||||
				{
 | 
			
		||||
					await AliasService.DeleteAliasAsync(a.AliasId);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
                NavigationManager.NavigateTo(NavigateUrl("admin/sites"));
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                AddModuleMessage(Localizer["Message.FailAuth.DeleteSite"], MessageType.Warning);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            await logger.LogError(ex, "Error Deleting Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
 | 
			
		||||
            AddModuleMessage(Localizer["Error.DeleteSite"], MessageType.Error);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
				NavigationManager.NavigateTo(NavigateUrl("admin/sites"));
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				AddModuleMessage(Localizer["Message.FailAuth.DeleteSite"], MessageType.Warning);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		catch (Exception ex)
 | 
			
		||||
		{
 | 
			
		||||
			await logger.LogError(ex, "Error Deleting Site {SiteId} {Error}", PageState.Site.SiteId, ex.Message);
 | 
			
		||||
			AddModuleMessage(Localizer["Error.DeleteSite"], MessageType.Error);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
    private async Task SendEmail()
 | 
			
		||||
    {
 | 
			
		||||
        if (_smtphost != "" && _smtpport != "" && _smtpsender != "")
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
 | 
			
		||||
                SettingService.SetSetting(settings, "SMTPHost", _smtphost);
 | 
			
		||||
                SettingService.SetSetting(settings, "SMTPPort", _smtpport);
 | 
			
		||||
                SettingService.SetSetting(settings, "SMTPSSL", _smtpssl);
 | 
			
		||||
                SettingService.SetSetting(settings, "SMTPUsername", _smtpusername);
 | 
			
		||||
                SettingService.SetSetting(settings, "SMTPPassword", _smtppassword);
 | 
			
		||||
                SettingService.SetSetting(settings, "SMTPSender", _smtpsender);
 | 
			
		||||
                await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
 | 
			
		||||
                await logger.LogInformation("Site SMTP Settings Saved");
 | 
			
		||||
	private async Task SendEmail()
 | 
			
		||||
	{
 | 
			
		||||
		if (_smtphost != "" && _smtpport != "" && _smtpsender != "")
 | 
			
		||||
		{
 | 
			
		||||
			try
 | 
			
		||||
			{
 | 
			
		||||
				var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
 | 
			
		||||
				SettingService.SetSetting(settings, "SMTPHost", _smtphost);
 | 
			
		||||
				SettingService.SetSetting(settings, "SMTPPort", _smtpport);
 | 
			
		||||
				SettingService.SetSetting(settings, "SMTPSSL", _smtpssl);
 | 
			
		||||
				SettingService.SetSetting(settings, "SMTPUsername", _smtpusername);
 | 
			
		||||
				SettingService.SetSetting(settings, "SMTPPassword", _smtppassword);
 | 
			
		||||
				SettingService.SetSetting(settings, "SMTPSender", _smtpsender);
 | 
			
		||||
				await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
 | 
			
		||||
				await logger.LogInformation("Site SMTP Settings Saved");
 | 
			
		||||
 | 
			
		||||
                await NotificationService.AddNotificationAsync(new Notification(PageState.Site.SiteId, PageState.User.DisplayName, PageState.User.Email, PageState.User.DisplayName, PageState.User.Email, PageState.Site.Name + " SMTP Configuration Test", "SMTP Server Is Configured Correctly."));
 | 
			
		||||
                AddModuleMessage(Localizer["Info.Smtp.SaveSettings"], MessageType.Info);
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                await logger.LogError(ex, "Error Testing SMTP Configuration");
 | 
			
		||||
                AddModuleMessage(Localizer["Error.Smtp.TestConfig"], MessageType.Error);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            AddModuleMessage(Localizer["Message.required.Smtp"], MessageType.Warning);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
				await NotificationService.AddNotificationAsync(new Notification(PageState.Site.SiteId, PageState.User.DisplayName, PageState.User.Email, PageState.User.DisplayName, PageState.User.Email, PageState.Site.Name + " SMTP Configuration Test", "SMTP Server Is Configured Correctly."));
 | 
			
		||||
				AddModuleMessage(Localizer["Info.Smtp.SaveSettings"], MessageType.Info);
 | 
			
		||||
			}
 | 
			
		||||
			catch (Exception ex)
 | 
			
		||||
			{
 | 
			
		||||
				await logger.LogError(ex, "Error Testing SMTP Configuration");
 | 
			
		||||
				AddModuleMessage(Localizer["Error.Smtp.TestConfig"], MessageType.Error);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			AddModuleMessage(Localizer["Message.required.Smtp"], MessageType.Warning);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private async Task GetAliases()
 | 
			
		||||
	{
 | 
			
		||||
		_urls = string.Empty;
 | 
			
		||||
		_defaultalias = string.Empty;
 | 
			
		||||
		_aliases = await AliasService.GetAliasesAsync();
 | 
			
		||||
		foreach (Alias alias in _aliases.Where(item => item.SiteId == PageState.Site.SiteId && item.TenantId == PageState.Site.TenantId).ToList())
 | 
			
		||||
		{
 | 
			
		||||
			_urls += (_urls == string.Empty) ? alias.Name : ", " + alias.Name;
 | 
			
		||||
			if (alias.IsDefault && string.IsNullOrEmpty(_defaultalias))
 | 
			
		||||
			{
 | 
			
		||||
				_defaultalias = alias.Name;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
@namespace Oqtane.Modules.Admin.Sites
 | 
			
		||||
@using Oqtane.Interfaces
 | 
			
		||||
@using System.Text.RegularExpressions
 | 
			
		||||
@inherits ModuleBase
 | 
			
		||||
@inject NavigationManager NavigationManager
 | 
			
		||||
@inject ITenantService TenantService
 | 
			
		||||
@ -282,6 +283,7 @@ else
 | 
			
		||||
        {
 | 
			
		||||
            if (_tenantid != "-" && _name != string.Empty && _urls != string.Empty && _themetype != "-" && _containertype != "-" && _sitetemplatetype != "-")
 | 
			
		||||
            {
 | 
			
		||||
				_urls = Regex.Replace(_urls, @"\r\n?|\n", ",");
 | 
			
		||||
                var duplicates = new List<string>();
 | 
			
		||||
                var aliases = await AliasService.GetAliasesAsync();
 | 
			
		||||
                foreach (string name in _urls.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ else
 | 
			
		||||
        _sites = new List<Alias>();
 | 
			
		||||
        foreach (Alias alias in aliases)
 | 
			
		||||
        {
 | 
			
		||||
            if (!_sites.Exists(item => item.TenantId == alias.TenantId && item.SiteId == alias.SiteId))
 | 
			
		||||
            if (alias.IsDefault && !_sites.Exists(item => item.TenantId == alias.TenantId && item.SiteId == alias.SiteId))
 | 
			
		||||
            {
 | 
			
		||||
                _sites.Add(alias);
 | 
			
		||||
            }
 | 
			
		||||
@ -52,16 +52,11 @@ else
 | 
			
		||||
 | 
			
		||||
    private void Edit(string name)
 | 
			
		||||
    {
 | 
			
		||||
        if (name.Equals("*"))
 | 
			
		||||
        {
 | 
			
		||||
            var uri = new Uri(NavigationManager.Uri);
 | 
			
		||||
            name = uri.Authority;
 | 
			
		||||
        }
 | 
			
		||||
        NavigationManager.NavigateTo(_scheme + name + "/admin/site/?reload");
 | 
			
		||||
        NavigationManager.NavigateTo(_scheme + name + "/admin/site", true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void Browse(string name)
 | 
			
		||||
    {
 | 
			
		||||
        NavigationManager.NavigateTo(_scheme + name + "/?reload");
 | 
			
		||||
        NavigationManager.NavigateTo(_scheme + name, true);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -129,9 +129,6 @@
 | 
			
		||||
  <data name="DefaultContainer.Text" xml:space="preserve">
 | 
			
		||||
    <value>Default Container: </value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="Appearance.Heading" xml:space="preserve">
 | 
			
		||||
    <value>Appearance</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="DefaultAdminContainer" xml:space="preserve">
 | 
			
		||||
    <value>Default Admin Container</value>
 | 
			
		||||
  </data>
 | 
			
		||||
@ -223,7 +220,7 @@
 | 
			
		||||
    <value>Aliases: </value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="IsDeleted.Text" xml:space="preserve">
 | 
			
		||||
    <value>Is Deleted? </value>
 | 
			
		||||
    <value>Deleted? </value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="Logo.Text" xml:space="preserve">
 | 
			
		||||
    <value>Logo: </value>
 | 
			
		||||
@ -318,4 +315,13 @@
 | 
			
		||||
  <data name="DeleteSite.Text" xml:space="preserve">
 | 
			
		||||
    <value>Delete Site</value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="DefaultAlias.HelpText" xml:space="preserve">
 | 
			
		||||
    <value>The default alias for the site. Requests for non-default aliases will be redirected to the default alias.</value>
 | 
			
		||||
  </data>
 | 
			
		||||
    <data name="DefaultAlias.Text" xml:space="preserve">
 | 
			
		||||
    <value>Default Alias: </value>
 | 
			
		||||
  </data>
 | 
			
		||||
  <data name="Aliases.Heading" xml:space="preserve">
 | 
			
		||||
    <value>Aliases</value>
 | 
			
		||||
  </data>
 | 
			
		||||
</root>
 | 
			
		||||
@ -152,7 +152,7 @@ namespace Oqtane.Services
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    if (setting.SettingValue != kvp.Value)
 | 
			
		||||
                    if (setting.SettingValue != value || setting.IsPublic != ispublic)
 | 
			
		||||
                    {
 | 
			
		||||
                        setting.SettingValue = value;
 | 
			
		||||
                        setting.IsPublic = ispublic;
 | 
			
		||||
 | 
			
		||||
@ -367,7 +367,9 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
                            tenant = db.Tenant.FirstOrDefault(item => item.Name == install.TenantName);
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        foreach (var aliasName in install.Aliases.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries))
 | 
			
		||||
                        var aliasNames = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray();
 | 
			
		||||
                        var firstAlias = aliasNames[0];
 | 
			
		||||
                        foreach (var aliasName in aliasNames)
 | 
			
		||||
                        {
 | 
			
		||||
                            if (tenant != null)
 | 
			
		||||
                            {
 | 
			
		||||
@ -376,6 +378,7 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
                                    Name = aliasName,
 | 
			
		||||
                                    TenantId = tenant.TenantId,
 | 
			
		||||
                                    SiteId = -1,
 | 
			
		||||
                                    IsDefault = (aliasName == firstAlias),
 | 
			
		||||
                                    CreatedBy = "",
 | 
			
		||||
                                    CreatedOn = DateTime.UtcNow,
 | 
			
		||||
                                    ModifiedBy = "",
 | 
			
		||||
@ -558,7 +561,8 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
                    {
 | 
			
		||||
                        // set the alias explicitly so the tenant can be resolved
 | 
			
		||||
                        var aliases = scope.ServiceProvider.GetRequiredService<IAliasRepository>();
 | 
			
		||||
                        var firstAlias = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)[0];
 | 
			
		||||
                        var aliasNames = install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(sValue => sValue.Trim()).ToArray();
 | 
			
		||||
                        var firstAlias = aliasNames[0];
 | 
			
		||||
                        var alias = aliases.GetAliases().FirstOrDefault(item => item.Name == firstAlias);
 | 
			
		||||
                        var tenantManager = scope.ServiceProvider.GetRequiredService<ITenantManager>();
 | 
			
		||||
                        tenantManager.SetAlias(alias);
 | 
			
		||||
@ -650,7 +654,7 @@ namespace Oqtane.Infrastructure
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            foreach (var aliasName in install.Aliases.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
 | 
			
		||||
                            foreach (var aliasName in aliasNames)
 | 
			
		||||
                            {
 | 
			
		||||
                                alias = aliases.GetAliases().FirstOrDefault(item => item.Name == aliasName);
 | 
			
		||||
                                if (alias != null)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								Oqtane.Server/Migrations/Master/03000201_AddAliasRedirect.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								Oqtane.Server/Migrations/Master/03000201_AddAliasRedirect.cs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
using Microsoft.EntityFrameworkCore.Infrastructure;
 | 
			
		||||
using Microsoft.EntityFrameworkCore.Migrations;
 | 
			
		||||
using Oqtane.Databases.Interfaces;
 | 
			
		||||
using Oqtane.Migrations.EntityBuilders;
 | 
			
		||||
using Oqtane.Repository;
 | 
			
		||||
 | 
			
		||||
namespace Oqtane.Migrations.Master
 | 
			
		||||
{
 | 
			
		||||
    [DbContext(typeof(MasterDBContext))]
 | 
			
		||||
    [Migration("Master.03.00.02.01")]
 | 
			
		||||
    public class AddAliasRedirect : MultiDatabaseMigration
 | 
			
		||||
    {
 | 
			
		||||
        public AddAliasRedirect(IDatabase database) : base(database)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void Up(MigrationBuilder migrationBuilder)
 | 
			
		||||
        {
 | 
			
		||||
            //Add Column to Alias table
 | 
			
		||||
            var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase);
 | 
			
		||||
            aliasEntityBuilder.AddBooleanColumn("IsDefault", true);
 | 
			
		||||
            aliasEntityBuilder.UpdateColumn("IsDefault", "1", "bool", "");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void Down(MigrationBuilder migrationBuilder)
 | 
			
		||||
        {
 | 
			
		||||
            var aliasEntityBuilder = new AliasEntityBuilder(migrationBuilder, ActiveDatabase);
 | 
			
		||||
            aliasEntityBuilder.DropColumn("IsDefault");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -18,6 +18,7 @@ using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Microsoft.Net.Http.Headers;
 | 
			
		||||
using Microsoft.AspNetCore.Http;
 | 
			
		||||
using System.Security.Claims;
 | 
			
		||||
using System.Net;
 | 
			
		||||
 | 
			
		||||
namespace Oqtane.Pages
 | 
			
		||||
{
 | 
			
		||||
@ -32,8 +33,9 @@ namespace Oqtane.Pages
 | 
			
		||||
        private readonly IPageRepository _pages;
 | 
			
		||||
        private readonly IUrlMappingRepository _urlMappings;
 | 
			
		||||
        private readonly IVisitorRepository _visitors;
 | 
			
		||||
        private readonly IAliasRepository _aliases;
 | 
			
		||||
 | 
			
		||||
        public HostModel(IConfiguration configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, ISiteRepository sites, IPageRepository pages, IUrlMappingRepository urlMappings, IVisitorRepository visitors)
 | 
			
		||||
        public HostModel(IConfiguration configuration, ITenantManager tenantManager, ILocalizationManager localizationManager, ILanguageRepository languages, IAntiforgery antiforgery, ISiteRepository sites, IPageRepository pages, IUrlMappingRepository urlMappings, IVisitorRepository visitors, IAliasRepository aliases)
 | 
			
		||||
        {
 | 
			
		||||
            _configuration = configuration;
 | 
			
		||||
            _tenantManager = tenantManager;
 | 
			
		||||
@ -44,6 +46,7 @@ namespace Oqtane.Pages
 | 
			
		||||
            _pages = pages;
 | 
			
		||||
            _urlMappings = urlMappings;
 | 
			
		||||
            _visitors = visitors;
 | 
			
		||||
            _aliases = aliases;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public string AntiForgeryToken = "";
 | 
			
		||||
@ -77,11 +80,25 @@ namespace Oqtane.Pages
 | 
			
		||||
                var alias = _tenantManager.GetAlias();
 | 
			
		||||
                if (alias != null)
 | 
			
		||||
                {
 | 
			
		||||
                    Route route = new Route(HttpContext.Request.GetEncodedUrl(), alias.Path);
 | 
			
		||||
                    var url = WebUtility.UrlDecode(HttpContext.Request.GetEncodedUrl());
 | 
			
		||||
 | 
			
		||||
                    // redirect non-default alias
 | 
			
		||||
                    if (!alias.IsDefault)
 | 
			
		||||
                    {
 | 
			
		||||
                        var redirect = _aliases.GetAliases()
 | 
			
		||||
                            .Where(item => item.TenantId == alias.TenantId && item.SiteId == alias.SiteId && item.IsDefault)
 | 
			
		||||
                            .FirstOrDefault();
 | 
			
		||||
                        if (redirect != null)
 | 
			
		||||
                        {
 | 
			
		||||
                            return RedirectPermanent(url.Replace(alias.Name, redirect.Name));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    var site = _sites.GetSite(alias.SiteId);
 | 
			
		||||
                    if (site != null)
 | 
			
		||||
                    {
 | 
			
		||||
                        Route route = new Route(url, alias.Path);
 | 
			
		||||
 | 
			
		||||
                        if (!string.IsNullOrEmpty(site.Runtime))
 | 
			
		||||
                        {
 | 
			
		||||
                            Runtime = site.Runtime;
 | 
			
		||||
@ -128,7 +145,7 @@ namespace Oqtane.Pages
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            // page does not exist
 | 
			
		||||
                            var url = route.SiteUrl + "/" + route.PagePath;
 | 
			
		||||
                            url = route.SiteUrl + "/" + route.PagePath;
 | 
			
		||||
                            var urlMapping = _urlMappings.GetUrlMapping(site.SiteId, url);
 | 
			
		||||
                            if (urlMapping != null && !string.IsNullOrEmpty(urlMapping.MappedUrl))
 | 
			
		||||
                            {
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ using System.Linq;
 | 
			
		||||
using Microsoft.EntityFrameworkCore;
 | 
			
		||||
using Microsoft.Extensions.Caching.Memory;
 | 
			
		||||
using Oqtane.Models;
 | 
			
		||||
using Oqtane.Shared;
 | 
			
		||||
 | 
			
		||||
namespace Oqtane.Repository
 | 
			
		||||
{
 | 
			
		||||
@ -72,7 +73,7 @@ namespace Oqtane.Repository
 | 
			
		||||
            int start = segments.Length;
 | 
			
		||||
            for (int i = 0; i < segments.Length; i++)
 | 
			
		||||
            {
 | 
			
		||||
                if (segments[i] == "api" || segments[i] == "pages" || segments[i] == "*")
 | 
			
		||||
                if (segments[i] == "api" || segments[i] == "pages" || segments[i] == Constants.ModuleDelimiter)
 | 
			
		||||
                {
 | 
			
		||||
                    start = i;
 | 
			
		||||
                    break;
 | 
			
		||||
@ -89,8 +90,18 @@ namespace Oqtane.Repository
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // return fallback alias if none found
 | 
			
		||||
            return alias ?? aliases.Find(item => item.Name.Equals("*"));
 | 
			
		||||
            // auto register alias if there is only a single tenant/site
 | 
			
		||||
            if (alias == null && aliases.Select(item => new { item.TenantId, item.SiteId }).Distinct().Count() == 1)
 | 
			
		||||
            {
 | 
			
		||||
                alias = new Alias();
 | 
			
		||||
                alias.TenantId = aliases.First().TenantId;
 | 
			
		||||
                alias.SiteId = aliases.First().SiteId;
 | 
			
		||||
                alias.Name = url;
 | 
			
		||||
                alias.IsDefault = false;
 | 
			
		||||
                alias = AddAlias(alias);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return alias;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void DeleteAlias(int aliasId)
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,11 @@ namespace Oqtane.Models
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public int SiteId { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Specifies if the alias is the default for the tenant/site. Requests for non-default aliases are redirected to the default alias.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public bool IsDefault { get; set; }
 | 
			
		||||
 | 
			
		||||
        /// <inheritdoc />
 | 
			
		||||
        public string CreatedBy { get; set; }
 | 
			
		||||
 | 
			
		||||
@ -62,5 +67,6 @@ namespace Oqtane.Models
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ namespace Oqtane.Models
 | 
			
		||||
            Action = "";
 | 
			
		||||
            UrlParameters = "";
 | 
			
		||||
 | 
			
		||||
            if (AliasPath.Length != 0)
 | 
			
		||||
            if (AliasPath.Length != 0 && PagePath.StartsWith("/" + AliasPath))
 | 
			
		||||
            {
 | 
			
		||||
                PagePath = PagePath.Substring(AliasPath.Length + 1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user