The authorization flow is: • Host tabs: Only Host (Admin blocked by Step 1) • Everything else: Admin bypasses, others check permissions
149 lines
5.4 KiB
Plaintext
149 lines
5.4 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 hierarchy:
|
|
/// 1. Host and Admin roles ALWAYS have access (bypass all checks)
|
|
/// 2. Check standard SecurityAccessLevel (View, Edit, etc.)
|
|
/// 3. If RoleName specified AND user is not Admin/Host, check RoleName
|
|
/// 4. If PermissionName specified AND user is not Admin/Host, check PermissionName
|
|
/// </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)
|
|
{
|
|
// Only Host users can access Host-level security tabs (Admin users are excluded)
|
|
return UserSecurity.IsAuthorized(PageState.User, RoleNames.Host);
|
|
}
|
|
|
|
// Step 2: Admin bypass all other restrictions
|
|
if (UserSecurity.IsAuthorized(PageState.User, RoleNames.Admin))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
var authorized = false;
|
|
|
|
// Step 3: Check standard SecurityAccessLevel
|
|
switch (tabPanel.Security)
|
|
{
|
|
case null:
|
|
authorized = true;
|
|
break;
|
|
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: Check RoleName if provided (additional requirement)
|
|
if (authorized && !string.IsNullOrEmpty(tabPanel.RoleName))
|
|
{
|
|
authorized = UserSecurity.IsAuthorized(PageState.User, tabPanel.RoleName);
|
|
}
|
|
|
|
// Step 5: Check PermissionName if provided (additional requirement)
|
|
if (authorized && !string.IsNullOrEmpty(tabPanel.PermissionName))
|
|
{
|
|
authorized = UserSecurity.IsAuthorized(PageState.User, tabPanel.PermissionName, ModuleState.PermissionList);
|
|
}
|
|
|
|
return authorized;
|
|
}
|
|
}
|