Reputation: 33
On Kentico 12, the property Security inside the Page doesn't have Access field like the previous version Kentico 11 - Interface Access.
I need to provide this feature, so I was thinking about using overriding the OnAuthentication method like this:
protected override void OnAuthentication(AuthenticationContext filterContext)
{
var isAuthenticated = filterContext.Principal.Identity.IsAuthenticated;
var routePath = filterContext.HttpContext.Request.Path;
var page = DocumentHelper.GetDocuments().Path(routePath).FirstOrDefault();
var allowAccess = (page.HasSecureProperty && isAuthenticated) || !page.HasSecureProperty;
if (allowAccess)
{
base.OnAuthentication(filterContext);
}
else
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { controller = "Account", action = "Signin" })
);
}
}
HasSecureProperty would be the property from the kentico page that admins or editors users can set on the administration panel. I was planning to create this property using custom table and make a interface on the page for the users.
The field IsSecureNode on CMS_Tree seems to be the property that I need and was been used on previous versions, but I couldn't find a way to set on the new admin panel.
Is there another solution to allow users to set authentication on pages? I was concerned about performance since this method will be called on every action. Thank you.
Upvotes: 0
Views: 756
Reputation: 33
I ended up using a custom table with an interface for the user to set if the page requires authentication or not. Since this is an override of OnAuthentication, every page calls this method. I hope there is a better solution using built-in Kentico features. Here is the final code:
protected override void OnAuthentication(AuthenticationContext filterContext)
{
base.OnAuthentication(filterContext);
var routePath = filterContext.HttpContext.Request.Path;
var allowAccess = Authentication.CanEnterPage(filterContext.Principal.Identity.IsAuthenticated, routePath);
if (!allowAccess)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(new { controller = "Account", action = "Signin", returnUrl = routePath })
);
}
}
The static method below contains the logic to access the page:
public static bool CanEnterPage(bool isAuthenticated, string routePath)
{
var page = DocumentHelper.GetDocuments().Path(routePath).FirstOrDefault();
if (page == null)
return false;
var pageAccess = PageAccessInfoProvider.GetPageAccesses()
.WhereEquals("PageAccessNodeID", page.NodeID).FirstOrDefault();
// Create a record if pageAccess is null
if (pageAccess == null)
{
pageAccess = CreateRecordsPageAccess(page);
}
var isSecure = pageAccess.PageAccessHasAuthentication;
var allowAccess = isSecure && isAuthenticated || !isSecure;
return allowAccess;
}
Upvotes: 0
Reputation: 995
You can use the approach mentioned in the documentation on authorizing live site actions.
Upvotes: 0
Reputation: 756
I have done something similar so maybe it will help point you in the right direction.
My entire MVC site requires authentication, so that might be where this differs. In the MVC when I want to get files and check permissions I do something like this:
var files = subcat.Children.WithAllData.WithPermissionsCheck;
On the CMS side, I have a field on the page type that allows a user to select roles and another one for selecting users. I then have a custom event on the document update or insert to update the settings.
Here is the code I use for updating the ACLs:
private void UpdateSettings(TreeNode node)
{
ObjectQuery<RoleInfo> roles = null;
ObjectQuery<UserInfo> users = null;
var columnRoles = node.GetStringValue("Roles", "");
if (columnRoles != "")
{
var rolesConcat = columnRoles.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var where = "RoleName IN " + "('" + string.Join("','", rolesConcat) + "')";
EventLogProvider.LogInformation("Document Event", "Roles", where);
roles = RoleInfoProvider.GetRoles()
.Where(where);
}
var columnUsers = node.GetStringValue("Users", "");
if (columnUsers != "")
{
var usersConcat = columnUsers.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var where = "UserName IN " + "('" + string.Join("','", usersConcat) + "')";
EventLogProvider.LogInformation("Document Event", "Users", where);
users = UserInfoProvider.GetUsers()
.Where(where);
}
if (node != null)
{
// Gets the ID of the ACL item that stores the page's permission settings
int nodeACLID = ValidationHelper.GetInteger(node.GetValue("NodeACLID"), 0);
// Deletes the page's ACL item
// Removes the page's permission settings for all users and roles
AclItemInfoProvider.DeleteAclItems(nodeACLID);
node.IsSecuredNode = true;
int allowed = DocumentSecurityHelper.GetNodePermissionFlags(NodePermissionsEnum.Read);
// Prepares a value indicating that no page permissions are denied
int denied = 0;
if (users != null)
foreach (var user in users)
{
// Sets the page's permission for the user (allows the 'Modify' permission)
AclItemInfoProvider.SetUserPermissions(node, allowed, denied, user);
}
if (roles != null)
foreach (var role in roles)
{
// Sets the page's permission for the user (allows the 'Modify' permission)
AclItemInfoProvider.SetRolePermissions(node, allowed, denied, role);
}
}
}
Upvotes: 0