Merge branch 'dev' into pager

This commit is contained in:
Hisham Bin Ateya
2022-06-07 23:37:08 +03:00
committed by GitHub
18 changed files with 500 additions and 400 deletions

View File

@ -63,8 +63,8 @@
<Label Class="col-sm-3" For="password" HelpText="Provide a password for the primary user account" ResourceKey="Password">Password:</Label> <Label Class="col-sm-3" For="password" HelpText="Provide a password for the primary user account" ResourceKey="Password">Password:</Label>
<div class="col-sm-9"> <div class="col-sm-9">
<div class="input-group"> <div class="input-group">
<input id="password" type="@_passwordtype" class="form-control" @bind="@_hostPassword" autocomplete="new-password" /> <input id="password" type="@_passwordType" class="form-control" @bind="@_hostPassword" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button> <button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglePassword</button>
</div> </div>
</div> </div>
</div> </div>
@ -72,8 +72,8 @@
<Label Class="col-sm-3" For="confirm" HelpText="Please confirm the password entered above by entering it again" ResourceKey="Confirm">Confirm:</Label> <Label Class="col-sm-3" For="confirm" HelpText="Please confirm the password entered above by entering it again" ResourceKey="Confirm">Confirm:</Label>
<div class="col-sm-9"> <div class="col-sm-9">
<div class="input-group"> <div class="input-group">
<input id="confirm" type="@_passwordtype" class="form-control" @bind="@_confirmPassword" autocomplete="new-password" /> <input id="confirm" type="@_confirmPasswordType" class="form-control" @bind="@_confirmPassword" autocomplete="new-password" />
<button type="button" class="btn btn-secondary" @onclick="@TogglePassword">@_togglepassword</button> <button type="button" class="btn btn-secondary" @onclick="@ToggleConfirmPassword">@_toggleConfirmPassword</button>
</div> </div>
</div> </div>
</div> </div>
@ -110,8 +110,10 @@
private string _hostUsername = string.Empty; private string _hostUsername = string.Empty;
private string _hostPassword = string.Empty; private string _hostPassword = string.Empty;
private string _passwordtype = "password"; private string _passwordType = "password";
private string _togglepassword = string.Empty; private string _confirmPasswordType = "password";
private string _togglePassword = string.Empty;
private string _toggleConfirmPassword = 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 bool _register = true;
@ -120,8 +122,11 @@
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
_togglepassword = SharedLocalizer["ShowPassword"]; _togglePassword = SharedLocalizer["ShowPassword"];
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
_databases = await DatabaseService.GetDatabasesAsync(); _databases = await DatabaseService.GetDatabasesAsync();
if (_databases.Exists(item => item.IsDefault)) if (_databases.Exists(item => item.IsDefault))
{ {
_databaseName = _databases.Find(item => item.IsDefault).Name; _databaseName = _databases.Find(item => item.IsDefault).Name;
@ -230,15 +235,29 @@
private void TogglePassword() private void TogglePassword()
{ {
if (_passwordtype == "password") if (_passwordType == "password")
{ {
_passwordtype = "text"; _passwordType = "text";
_togglepassword = SharedLocalizer["HidePassword"]; _togglePassword = SharedLocalizer["HidePassword"];
} }
else else
{ {
_passwordtype = "password"; _passwordType = "password";
_togglepassword = SharedLocalizer["ShowPassword"]; _togglePassword = SharedLocalizer["ShowPassword"];
}
}
private void ToggleConfirmPassword()
{
if (_confirmPasswordType == "password")
{
_confirmPasswordType = "text";
_toggleConfirmPassword = SharedLocalizer["HidePassword"];
}
else
{
_confirmPasswordType = "password";
_toggleConfirmPassword = SharedLocalizer["ShowPassword"];
} }
} }
} }

View File

@ -198,6 +198,7 @@
var module = ModuleState; var module = ModuleState;
module.AllPages = bool.Parse(_allPages); module.AllPages = bool.Parse(_allPages);
module.PageModuleId = ModuleState.PageModuleId;
module.Permissions = _permissionGrid.GetPermissions(); module.Permissions = _permissionGrid.GetPermissions();
await ModuleService.UpdateModuleAsync(module); await ModuleService.UpdateModuleAsync(module);

View File

@ -59,7 +59,7 @@ else
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{ {
_roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true); _roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
_roles = _roles.Where(item => item.Name != RoleNames.Everyone).ToList(); _roles.RemoveAll(item => item.Name == RoleNames.Everyone || item.Name == RoleNames.Unauthenticated);
} }
else else
{ {

View File

@ -88,15 +88,17 @@ else
userid = Int32.Parse(PageState.QueryString["id"]); userid = Int32.Parse(PageState.QueryString["id"]);
User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId); User user = await UserService.GetUserAsync(userid, PageState.Site.SiteId);
name = user.DisplayName; name = user.DisplayName;
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{ {
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true); roles = await RoleService.GetRolesAsync(PageState.Site.SiteId, true);
roles = roles.Where(item => item.Name != RoleNames.Everyone).ToList(); roles.RemoveAll(item => item.Name == RoleNames.Everyone || item.Name == RoleNames.Unauthenticated);
} }
else else
{ {
roles = await RoleService.GetRolesAsync(PageState.Site.SiteId); roles = await RoleService.GetRolesAsync(PageState.Site.SiteId);
} }
await GetUserRoles(); await GetUserRoles();
} }
catch (Exception ex) catch (Exception ex)

View File

@ -310,6 +310,17 @@
var interop = new Interop(JSRuntime); var interop = new Interop(JSRuntime);
var upload = await interop.GetFiles(_fileinputid); var upload = await interop.GetFiles(_fileinputid);
if (upload.Length > 0) if (upload.Length > 0)
{
string restricted = "";
foreach (var file in upload)
{
var extension = (file.LastIndexOf(".") != -1) ? file.Substring(file.LastIndexOf(".") + 1) : "";
if (!Constants.UploadableFiles.Split(',').Contains(extension.ToLower()))
{
restricted += (restricted == "" ? "" : ",") + extension;
}
}
if (restricted == "")
{ {
try try
{ {
@ -360,6 +371,12 @@
} }
} }
else else
{
_message = string.Format(Localizer["Message.File.Restricted"], restricted);
_messagetype = MessageType.Warning;
}
}
else
{ {
_message = Localizer["Message.File.NotSelected"]; _message = Localizer["Message.File.NotSelected"];
_messagetype = MessageType.Warning; _messagetype = MessageType.Warning;

View File

@ -127,11 +127,10 @@
_permissionnames = PermissionNames; _permissionnames = PermissionNames;
} }
_roles = await RoleService.GetRolesAsync(ModuleState.SiteId); _roles = await RoleService.GetRolesAsync(ModuleState.SiteId, true);
_roles.Insert(0, new Role { Name = RoleNames.Everyone }); if (!UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{ {
_roles.Add(new Role { Name = RoleNames.Host }); _roles.RemoveAll(item => item.Name == RoleNames.Host);
} }
_permissions = new List<PermissionString>(); _permissions = new List<PermissionString>();
@ -254,6 +253,7 @@
permission = _permissions[i]; permission = _permissions[i];
List<string> ids = permission.Permissions.Split(';', StringSplitOptions.RemoveEmptyEntries).ToList(); List<string> ids = permission.Permissions.Split(';', StringSplitOptions.RemoveEmptyEntries).ToList();
ids.Remove("!" + RoleNames.Everyone); // remove deny all users ids.Remove("!" + RoleNames.Everyone); // remove deny all users
ids.Remove("!" + RoleNames.Unauthenticated); // remove deny unauthenticated
ids.Remove("!" + RoleNames.Registered); // remove deny registered users ids.Remove("!" + RoleNames.Registered); // remove deny registered users
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host)) if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Host))
{ {

View File

@ -141,4 +141,7 @@
<data name="Success.File.Upload" xml:space="preserve"> <data name="Success.File.Upload" xml:space="preserve">
<value>File Upload Succeeded</value> <value>File Upload Succeeded</value>
</data> </data>
<data name="Message.File.Restricted" xml:space="preserve">
<value>Files With Extension Of {0} Are Restricted From Upload. Please Contact Your Administrator For More Information.</value>
</data>
</root> </root>

View File

@ -327,4 +327,13 @@
<data name="ShowPassword" xml:space="preserve"> <data name="ShowPassword" xml:space="preserve">
<value>Show</value> <value>Show</value>
</data> </data>
<data name="PageOfPages" xml:space="preserve">
<value>Page {0} of {1}</value>
</data>
<data name="Url Mappings" xml:space="preserve">
<value>Url Mappings</value>
</data>
<data name="Visitor Management" xml:space="preserve">
<value>Visitor Management</value>
</data>
</root> </root>

View File

@ -276,9 +276,17 @@ namespace Oqtane.Controllers
return; return;
} }
if (!formfile.FileName.IsPathOrFileValid()) // ensure filename is valid
string token = ".part_";
if (!formfile.FileName.IsPathOrFileValid() || !formfile.FileName.Contains(token))
{
return;
}
// check for allowable file extensions (ignore token)
var extension = Path.GetExtension(formfile.FileName.Substring(0, formfile.FileName.IndexOf(token))).Replace(".", "");
if (!Constants.UploadableFiles.Split(',').Contains(extension.ToLower()))
{ {
HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
return; return;
} }
@ -331,9 +339,9 @@ namespace Oqtane.Controllers
{ {
string merged = ""; string merged = "";
// parse the filename which is in the format of filename.ext.part_x_y // parse the filename which is in the format of filename.ext.part_001_999
string token = ".part_"; string token = ".part_";
string parts = Path.GetExtension(filename)?.Replace(token, ""); // returns "x_y" string parts = Path.GetExtension(filename)?.Replace(token, ""); // returns "001_999"
int totalparts = int.Parse(parts?.Substring(parts.IndexOf("_") + 1)); int totalparts = int.Parse(parts?.Substring(parts.IndexOf("_") + 1));
filename = Path.GetFileNameWithoutExtension(filename); // base filename filename = Path.GetFileNameWithoutExtension(filename); // base filename
@ -370,13 +378,6 @@ namespace Oqtane.Controllers
System.IO.File.Delete(filepart); System.IO.File.Delete(filepart);
} }
// check for allowable file extensions
if (!Constants.UploadableFiles.Split(',').Contains(Path.GetExtension(filename)?.ToLower().Replace(".", "")))
{
System.IO.File.Delete(Path.Combine(folder, filename + ".tmp"));
}
else
{
// remove file if it already exists // remove file if it already exists
if (System.IO.File.Exists(Path.Combine(folder, filename))) if (System.IO.File.Exists(Path.Combine(folder, filename)))
{ {
@ -386,7 +387,6 @@ namespace Oqtane.Controllers
// rename file now that the entire process is completed // rename file now that the entire process is completed
System.IO.File.Move(Path.Combine(folder, filename + ".tmp"), Path.Combine(folder, filename)); System.IO.File.Move(Path.Combine(folder, filename + ".tmp"), Path.Combine(folder, filename));
_logger.Log(LogLevel.Information, this, LogFunction.Create, "File Uploaded {File}", Path.Combine(folder, filename)); _logger.Log(LogLevel.Information, this, LogFunction.Create, "File Uploaded {File}", Path.Combine(folder, filename));
}
merged = filename; merged = filename;
} }
@ -394,8 +394,7 @@ namespace Oqtane.Controllers
// clean up file parts which are more than 2 hours old ( which can happen if a prior file upload failed ) // clean up file parts which are more than 2 hours old ( which can happen if a prior file upload failed )
var cleanupFiles = Directory.EnumerateFiles(folder, "*" + token + "*") var cleanupFiles = Directory.EnumerateFiles(folder, "*" + token + "*")
.Where(f => Path.GetExtension(f).StartsWith(token)); .Where(f => Path.GetExtension(f).StartsWith(token) && !Path.GetFileName(f).StartsWith(filename));
foreach (var file in cleanupFiles) foreach (var file in cleanupFiles)
{ {
var createdDate = System.IO.File.GetCreationTime(file).ToUniversalTime(); var createdDate = System.IO.File.GetCreationTime(file).ToUniversalTime();

View File

@ -139,24 +139,41 @@ namespace Oqtane.Controllers
[Authorize(Roles = RoleNames.Registered)] [Authorize(Roles = RoleNames.Registered)]
public Module Put(int id, [FromBody] Module module) public Module Put(int id, [FromBody] Module module)
{ {
if (ModelState.IsValid && module.SiteId == _alias.SiteId && _modules.GetModule(module.ModuleId, false) != null && _userPermissions.IsAuthorized(User, EntityNames.Module, module.ModuleId, PermissionNames.Edit)) var _module = _modules.GetModule(module.ModuleId, false);
if (ModelState.IsValid && module.SiteId == _alias.SiteId && _module != null && _userPermissions.IsAuthorized(User, EntityNames.Module, module.ModuleId, PermissionNames.Edit))
{ {
module = _modules.UpdateModule(module); module = _modules.UpdateModule(module);
if (_module.AllPages != module.AllPages)
{
var pageModules = _pageModules.GetPageModules(module.SiteId).ToList();
if (module.AllPages) if (module.AllPages)
{ {
var pageModule = _pageModules.GetPageModules(module.SiteId).FirstOrDefault(item => item.ModuleId == module.ModuleId); var pageModule = _pageModules.GetPageModule(module.PageModuleId);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Module Updated {Module}", module);
var pages = _pages.GetPages(module.SiteId).ToList(); var pages = _pages.GetPages(module.SiteId).ToList();
foreach (Page page in pages) foreach (Page page in pages)
{ {
if (page.PageId != pageModule.PageId && !page.Path.StartsWith("admin/")) if (!pageModules.Exists(item => item.ModuleId == module.ModuleId && item.PageId == page.PageId) && !page.Path.StartsWith("admin/"))
{ {
_pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType }); _pageModules.AddPageModule(new PageModule { PageId = page.PageId, ModuleId = pageModule.ModuleId, Title = pageModule.Title, Pane = pageModule.Pane, Order = pageModule.Order, ContainerType = pageModule.ContainerType });
} }
} }
} }
else
{
foreach (var pageModule in pageModules)
{
if (pageModule.ModuleId == module.ModuleId && pageModule.PageModuleId != module.PageModuleId)
{
_pageModules.DeletePageModule(pageModule.PageModuleId);
}
}
}
}
_syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId); _syncManager.AddSyncEvent(_alias.TenantId, EntityNames.Site, _alias.SiteId);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Module Updated {Module}", module);
} }
else else
{ {

View File

@ -50,6 +50,9 @@ namespace Oqtane.Infrastructure
case "3.0.1": case "3.0.1":
Upgrade_3_0_1(tenant, scope); Upgrade_3_0_1(tenant, scope);
break; break;
case "3.1.3":
Upgrade_3_1_3(tenant, scope);
break;
} }
} }
} }
@ -182,5 +185,15 @@ namespace Oqtane.Infrastructure
sites.CreatePages(site, pageTemplates); sites.CreatePages(site, pageTemplates);
} }
} }
private void Upgrade_3_1_3(Tenant tenant, IServiceScope scope)
{
var roles = scope.ServiceProvider.GetRequiredService<IRoleRepository>();
if (!roles.GetRoles(-1, true).ToList().Where(item => item.Name == RoleNames.Unauthenticated).Any())
{
roles.AddRole(new Role { SiteId = null, Name = RoleNames.Unauthenticated, Description = RoleNames.Unauthenticated, IsAutoAssigned = false, IsSystem = true });
}
}
} }
} }

View File

@ -94,16 +94,18 @@ namespace Oqtane.Repository
List<Role> roles = _roleRepository.GetRoles(site.SiteId, true).ToList(); List<Role> roles = _roleRepository.GetRoles(site.SiteId, true).ToList();
if (!roles.Where(item => item.Name == RoleNames.Everyone).Any()) if (!roles.Where(item => item.Name == RoleNames.Everyone).Any())
{ {
_roleRepository.AddRole(new Role {SiteId = null, Name = RoleNames.Everyone, Description = "All Users", IsAutoAssigned = false, IsSystem = true}); _roleRepository.AddRole(new Role {SiteId = null, Name = RoleNames.Everyone, Description = RoleNames.Everyone, IsAutoAssigned = false, IsSystem = true});
}
if (!roles.Where(item => item.Name == RoleNames.Unauthenticated).Any())
{
_roleRepository.AddRole(new Role { SiteId = null, Name = RoleNames.Unauthenticated, Description = RoleNames.Unauthenticated, IsAutoAssigned = false, IsSystem = true });
} }
if (!roles.Where(item => item.Name == RoleNames.Host).Any()) if (!roles.Where(item => item.Name == RoleNames.Host).Any())
{ {
_roleRepository.AddRole(new Role {SiteId = null, Name = RoleNames.Host, Description = "Application Administrators", IsAutoAssigned = false, IsSystem = true}); _roleRepository.AddRole(new Role {SiteId = null, Name = RoleNames.Host, Description = RoleNames.Host, IsAutoAssigned = false, IsSystem = true});
} }
_roleRepository.AddRole(new Role {SiteId = site.SiteId, Name = RoleNames.Registered, Description = RoleNames.Registered, IsAutoAssigned = true, IsSystem = true});
_roleRepository.AddRole(new Role {SiteId = site.SiteId, Name = RoleNames.Registered, Description = "Registered Users", IsAutoAssigned = true, IsSystem = true}); _roleRepository.AddRole(new Role {SiteId = site.SiteId, Name = RoleNames.Admin, Description = RoleNames.Admin, IsAutoAssigned = false, IsSystem = true});
_roleRepository.AddRole(new Role {SiteId = site.SiteId, Name = RoleNames.Admin, Description = "Site Administrators", IsAutoAssigned = false, IsSystem = true});
_profileRepository.AddProfile(new Profile _profileRepository.AddProfile(new Profile
{SiteId = site.SiteId, Name = "FirstName", Title = "First Name", Description = "Your First Or Given Name", Category = "Name", ViewOrder = 1, MaxLength = 50, DefaultValue = "", IsRequired = false, IsPrivate = false, Options = ""}); {SiteId = site.SiteId, Name = "FirstName", Title = "First Name", Description = "Your First Or Given Name", Category = "Name", ViewOrder = 1, MaxLength = 50, DefaultValue = "", IsRequired = false, IsPrivate = false, Options = ""});

View File

@ -344,10 +344,17 @@ Oqtane.Interop = {
progressinfo.innerHTML = file.name + ' 100%'; progressinfo.innerHTML = file.name + ' 100%';
progressbar.value = 1; progressbar.value = 1;
}; };
request.upload.onerror = function () {
progressinfo.innerHTML = file.name + ' Error: ' + xhr.status;
progressbar.value = 0;
};
request.send(data); request.send(data);
} }
}
if (i === files.length - 1) {
fileinput.value = ''; fileinput.value = '';
}
}
}, },
refreshBrowser: function (reload, wait) { refreshBrowser: function (reload, wait) {
setInterval(function () { setInterval(function () {

View File

@ -60,6 +60,7 @@ namespace Oqtane.Models
public Dictionary<string, string> Settings { get; set; } public Dictionary<string, string> Settings { get; set; }
#region PageModule properties #region PageModule properties
[NotMapped] [NotMapped]
public int PageModuleId { get; set; } public int PageModuleId { get; set; }
@ -68,6 +69,7 @@ namespace Oqtane.Models
/// </summary> /// </summary>
[NotMapped] [NotMapped]
public int PageId { get; set; } public int PageId { get; set; }
[NotMapped] [NotMapped]
public string Title { get; set; } public string Title { get; set; }
@ -76,8 +78,10 @@ namespace Oqtane.Models
/// </summary> /// </summary>
[NotMapped] [NotMapped]
public string Pane { get; set; } public string Pane { get; set; }
[NotMapped] [NotMapped]
public int Order { get; set; } public int Order { get; set; }
[NotMapped] [NotMapped]
public string ContainerType { get; set; } public string ContainerType { get; set; }

View File

@ -104,11 +104,14 @@ namespace Oqtane.Security
private static bool IsAllowed(int userId, string roles, string permission) private static bool IsAllowed(int userId, string roles, string permission)
{ {
if (permission == RoleNames.Unauthenticated)
{
return userId == -1;
}
if ("[" + userId + "]" == permission) if ("[" + userId + "]" == permission)
{ {
return true; return true;
} }
if (roles != null) if (roles != null)
{ {
return roles.IndexOf(";" + permission + ";") != -1; return roles.IndexOf(";" + permission + ";") != -1;

View File

@ -4,8 +4,8 @@ namespace Oqtane.Shared
{ {
public class Constants public class Constants
{ {
public static readonly string Version = "3.1.2"; public static readonly string Version = "3.1.3";
public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2"; public const string ReleaseVersions = "1.0.0,1.0.1,1.0.2,1.0.3,1.0.4,2.0.0,2.0.1,2.0.2,2.1.0,2.2.0,2.3.0,2.3.1,3.0.0,3.0.1,3.0.2,3.0.3,3.1.0,3.1.1,3.1.2,3.1.3";
public const string PackageId = "Oqtane.Framework"; public const string PackageId = "Oqtane.Framework";
public const string UpdaterPackageId = "Oqtane.Updater"; public const string UpdaterPackageId = "Oqtane.Updater";
public const string PackageRegistryUrl = "https://www.oqtane.net"; public const string PackageRegistryUrl = "https://www.oqtane.net";

View File

@ -1,8 +1,9 @@
namespace Oqtane.Shared { namespace Oqtane.Shared {
public class RoleNames { public class RoleNames {
public const string Everyone = "All Users"; public const string Everyone = "All Users";
public const string Host = "Host Users"; public const string Host = "Host Users";
public const string Admin = "Administrators"; public const string Admin = "Administrators";
public const string Registered = "Registered Users"; public const string Registered = "Registered Users";
public const string Unauthenticated = "Unauthenticated Users";
} }
} }

View File

@ -57,8 +57,11 @@ There is a separate [Documentation repository](https://github.com/oqtane/oqtane.
# Roadmap # Roadmap
This project is open source, and therefore is a work in progress... This project is open source, and therefore is a work in progress...
Backlog (Not Yet Assigned) V.4.0.0 ( Q4 2022 )
- [ ] Allow language specification in Url (#1731) - [ ] MAUI / Blazor Hybrid support
V.3.1.3 ( June 2022 )
- [ ] Stabilization improvements
V.3.1.2 ( May 14, 2022 ) V.3.1.2 ( May 14, 2022 )
- [x] Stabilization improvements - [x] Stabilization improvements