Updated the tab visibility logic to clarify and enforce the authorization hierarchy. Host-only tabs now strictly require the Host role, Admins bypass all checks except Host, and null SecurityAccessLevel still enforces RoleName and PermissionName if specified. Improved code comments for clarity and adjusted logic to ensure correct permission checks.
173 lines
6.5 KiB
Plaintext
173 lines
6.5 KiB
Plaintext
@namespace Oqtane.Modules.Controls
|
|
@inherits ModuleControlBase
|
|
|
|
<CascadingValue Value="this" IsFixed="true">
|
|
<div class="container-fluid">
|
|
<div class="form-group">
|
|
<ul class="nav nav-tabs" role="tablist">
|
|
@foreach (TabPanel tabPanel in _tabPanels)
|
|
{
|
|
<li class="nav-item" @key="tabPanel.Name">
|
|
@if (tabPanel.Name.ToLower() == ActiveTab.ToLower())
|
|
{
|
|
<a class="nav-link active" data-bs-toggle="tab" href="#@(Id + tabPanel.Name)" role="tab" @onclick:preventDefault="true">
|
|
@tabPanel.DisplayHeading()
|
|
</a>
|
|
}
|
|
else
|
|
{
|
|
<a class="nav-link" data-bs-toggle="tab" href="#@(Id + tabPanel.Name)" role="tab" @onclick:preventDefault="true">
|
|
@tabPanel.DisplayHeading()
|
|
</a>
|
|
}
|
|
</li>
|
|
}
|
|
</ul>
|
|
<div class="tab-content @TabContentClass">
|
|
<br />
|
|
@ChildContent
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CascadingValue>
|
|
|
|
@code {
|
|
private List<TabPanel> _tabPanels;
|
|
private string _tabpanelid = string.Empty;
|
|
|
|
[Parameter]
|
|
public RenderFragment ChildContent { get; set; } // contains the TabPanels
|
|
|
|
[Parameter]
|
|
public string ActiveTab { get; set; } // optional - defaults to first TabPanel if not specified. Can also be set using a "tab=" querystring parameter.
|
|
|
|
[Parameter]
|
|
public bool Refresh { get; set; } // optional - used in scenarios where TabPanels are added/removed dynamically within a parent form. ActiveTab may need to be reset as well when this property is used.
|
|
|
|
[Parameter]
|
|
public string Id { get; set; } // optional - used to uniquely identify an instance of a tab strip component (will be set automatically if no value provided)
|
|
|
|
[Parameter]
|
|
public string TabContentClass { get; set; } // optional - to extend the TabContent div.
|
|
|
|
protected override void OnInitialized()
|
|
{
|
|
if (string.IsNullOrEmpty(Id))
|
|
{
|
|
// create unique id for component
|
|
Id = "TabStrip_" + Guid.NewGuid().ToString("N") + "_" ;
|
|
}
|
|
}
|
|
|
|
protected override void OnParametersSet()
|
|
{
|
|
if (PageState.QueryString.ContainsKey("tab"))
|
|
{
|
|
ActiveTab = PageState.QueryString["tab"];
|
|
}
|
|
if (_tabPanels == null || Refresh)
|
|
{
|
|
_tabPanels = new List<TabPanel>();
|
|
}
|
|
}
|
|
|
|
internal void AddTabPanel(TabPanel tabPanel)
|
|
{
|
|
if (!_tabPanels.Exists(item => item.Name == tabPanel.Name) && IsAuthorized(tabPanel))
|
|
{
|
|
_tabPanels.Add(tabPanel);
|
|
StateHasChanged();
|
|
}
|
|
if (string.IsNullOrEmpty(ActiveTab))
|
|
{
|
|
ActiveTab = tabPanel.Name;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if a tab should be visible based on user permissions.
|
|
/// Authorization follows this hierarchy:
|
|
/// 1. Host tabs (Security == Host): Only users with Host role can access (Admins excluded)
|
|
/// 2. Admin users: Bypass all other checks (except Host restrictions)
|
|
/// 3. SecurityAccessLevel check (null/Anonymous/View/Edit/Host):
|
|
/// - null: No security level restriction (proceeds to step 4)
|
|
/// - Anonymous: No authentication required
|
|
/// - View/Edit: Requires corresponding module permission
|
|
/// - Host: Only Host role can access
|
|
/// 4. Additional RoleName requirement (if specified)
|
|
/// 5. Additional PermissionName requirement (if specified)
|
|
///
|
|
/// Important: When Security is null, RoleName and PermissionName checks STILL apply
|
|
/// (Security = null doesn't mean unrestricted, it means "no security level required")
|
|
/// </summary>
|
|
/// <param name="tabPanel">The tab panel to check authorization for</param>
|
|
/// <returns>True if user is authorized to see this tab, false otherwise</returns>
|
|
private bool IsAuthorized(TabPanel tabPanel)
|
|
{
|
|
// Step 1: Check for Host-only restriction
|
|
if (tabPanel.Security == SecurityAccessLevel.Host)
|
|
{
|
|
return UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
|
|
}
|
|
|
|
// Step 2: Admin bypass all restrictions except Host
|
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Step 3: If Security is null, check only RoleName and PermissionName
|
|
if (tabPanel.Security == null)
|
|
{
|
|
// Start with authorized = true for null security
|
|
bool isAuthorized = true;
|
|
|
|
// Only apply RoleName check if provided
|
|
if (!string.IsNullOrEmpty(tabPanel.RoleName))
|
|
{
|
|
isAuthorized = UserSecurity.IsAuthorized(PageState.User, tabPanel.RoleName);
|
|
}
|
|
|
|
// Only apply PermissionName check if provided
|
|
if (isAuthorized && !string.IsNullOrEmpty(tabPanel.PermissionName))
|
|
{
|
|
isAuthorized = UserSecurity.IsAuthorized(PageState.User, tabPanel.PermissionName, ModuleState.PermissionList);
|
|
}
|
|
|
|
return isAuthorized;
|
|
}
|
|
|
|
// Handle other SecurityAccessLevel values
|
|
bool authorized = false; // Use different variable name or move declaration
|
|
switch (tabPanel.Security)
|
|
{
|
|
case SecurityAccessLevel.Anonymous:
|
|
authorized = true;
|
|
break;
|
|
case SecurityAccessLevel.View:
|
|
authorized = UserSecurity.IsAuthorized(PageState.User, PermissionNames.View, ModuleState.PermissionList);
|
|
break;
|
|
case SecurityAccessLevel.Edit:
|
|
authorized = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.PermissionList);
|
|
break;
|
|
case SecurityAccessLevel.Host:
|
|
authorized = UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
|
|
break;
|
|
}
|
|
|
|
// Step 4: Additional RoleName requirement
|
|
if (authorized && !string.IsNullOrEmpty(tabPanel.RoleName))
|
|
{
|
|
authorized = UserSecurity.IsAuthorized(PageState.User, tabPanel.RoleName);
|
|
}
|
|
|
|
// Step 5: Additional PermissionName requirement
|
|
if (authorized && !string.IsNullOrEmpty(tabPanel.PermissionName))
|
|
{
|
|
authorized = UserSecurity.IsAuthorized(PageState.User, tabPanel.PermissionName, ModuleState.PermissionList);
|
|
}
|
|
|
|
return authorized;
|
|
}
|
|
}
|