Zend Navigation Multiple ACL roles - zend-framework

I am trying to create an ACL where users may have different roles in different departments.
The user is given a role in the form of role::guest or role::user depending if they are logged in. This is their userRole. (There is also a role::superuser that has access to all departments).
I have also added departmental roles to the ACL in the form of department::role (Eg. bookings::user). This is their departmentRole.
The users departmental roles are stored in the Zend_Auth identity.
The access control part works by extending Zend_Acl and over-riding the isAllowed function.
This successfully allows or denys each user.
public function isAllowed($role = null, $resource = null, $privilege = null)
{
$identity = Zend_Auth::getInstance()->getIdentity();
$userRole = $identity->role;
$departmentRoles = $identity->departmentRoles;
if (parent::isAllowed($userRole, $resource, $privilege))
{
return parent::isAllowed($userRole, $resource, $privilege);
}
else {
foreach ($departmentRoles as $departmentRole)
{
if(parent::isAllowed($departmentRole, $resource, $privilege))
{
return true;
}
}
}
return false;
}
The problem I am having is that Zend_Navigation requires an instance of the Acl and a single user role. My view script which builds the navigation menu uses $this->navigation()->accept($page) which only validates against the single user role.
How can I have multiple Acl roles for each user and have Zend_Navigation display menu items that they have access to?
If there is a better / different / correct approach to this please share.
Thanks
EDIT:
The fact that this approach meant over riding a core function in isAllowed() got me thinking this can't be the correct way to do this.
Now, in my ACL model I fetch all users, departments and associations and loop through creating an array for each user made up of their various roles within their relevant departments. I then create one role for each user and inherit the roles in the array previously created.
This is working well up to now and also means I can also add the users as resources and allow the relevant admin and department managers rights to amend their details etc.
It also means that I can pass a single role to Zend_Navigation and the menu structure should be relevant to their department roles.

IMHO having multiple ACL roles for single user looks like anti-pattern. Zend_Navigation rules are binded to (multiple) resources for single role which makes perferct sense.
What are your constraints that forbids you to allow resources for your (department) roles?
You can always use inheritance for your ACL roles.
If you prefer having multiple roles for single user, you might need to have separate ACL rules.
Zend_View_Helper_Navigation_HelperAbstract::setDefaultAcl($acl);
Zend_View_Helper_Navigation_HelperAbstract::setDefaultRole($role);

Related

Taking the Name of the ROLE the user is in and populating it to a pick-list on the Opportunity

My customer has created roles with the names of the company's business divisions and sub-divisions. He wants to take the role the creating user is in, along with the next level up Role and populate that into two fields on the opportunity, to then use those two fields. (ROLE and SUB-ROLE) as Dashboard filters. Since the role is in the setup section and is also not a field on the user record, I'm assuming some type of Apex Trigger or Flow would be needed to take the role names of the creating user and then insert them?
They are new to Salesforce.. they have not tried anything yet.

Keycloak - Manage realm with user from different realm

Is possible to have user in one realm to manage another realm in keycloak?
My goal is to have 2 realms - adminRealm & userRalm. In adminRealm should be users, which will be able to log in to our admin app and there they could create via Keycloak rest api "ordinary user" which will be placed into userRealm.
Currently my solution working over one realm, where I have admin user which is able to log into my admin app and there he can create users in the same realm. But if I want create users to another realm, I get 403 error. So is there any way how to allow admin user to manage another realm (eg create users etc.)?
You should use master realm for storing admin accounts. Non master realms are isolated from each other. If you look to the clients list in master realm you should see that every realm represented by client with OIDC id like "foo-realm". This clients represents administration REST API for corresponding realms, and users with granted roles from this clients could perform admin requests to corresponding apis.
For example you have foo realm which will contain ordinary application users. To achieve your goal to introduce admin accounts that will be able to manage users from foo you have to create foo-admin user in master realm and grant him foo-realm.realm-admin role. Now this user has total control over foo realm and no control over master realm. You also can map foo-realm.realm-admin role to some group in master realm and add users to it (so if any changes appears in future you will have to change only group role settings)
In case you use terraform your solution would look like this:
data "keycloak_realm" "master" {
realm = "master"
}
data "keycloak_openid_client" "realm_management" {
realm_id = data.keycloak_realm.master.id
client_id = "foo-realm"
}
data "keycloak_role" "query_users" {
realm_id = data.keycloak_realm.master.id
client_id = data.keycloak_openid_client.realm_management.id
name = "query-users"
}
data "keycloak_role" "manage_users" {
realm_id = data.keycloak_realm.master.id
client_id = data.keycloak_openid_client.realm_management.id
name = "manage-users"
}
resource "keycloak_user_roles" "user_admin_roles" {
realm_id = data.keycloak_realm.master.id
user_id = keycloak_user.users_admin.id
role_ids = [
data.keycloak_role.query_users.id,
data.keycloak_role.manage_users.id,
]
}

Is there a way to setup a field-level authorisation on FaunaDB + GraphQL?

I'm having troubles finding a way to hide user emails from everyone, except the owner (user has access to only his email). Is there a way to hide a certain document field, for a certain roles?
Here is an example I found that creates a role with dynamic access to the whole User collection:
CreateRole({
name: "tier1_role",
membership: {
resource: Collection("User"),
predicate: Query(
Lambda("userRef",
// User attribute based rule:
// It grants access only if the User has TIER1 role.
// If so, further rules specified in the privileges
// section are applied next.
Equals(Select(["data", "role"], Get(Var("userRef"))), "TIER1")
)
)
},
privileges: [
{
// Note: 'allUsers' Index is used to retrieve the
// documents from the File collection. Therefore,
// read access to the Index is required here as well.
resource: Index("allUsers"),
actions: { read: true }
}
]
})
I tried to change it a bit, but I wasn't able to set up field-level access.
Let's say I'd set up FaunaDB with GraphQL schema below.
enum UserRole {
TIER1
}
type User {
email: String! #unique
username: String! #unique
role: UserRole!
}
type Query {
allUsers: [User!]
}
type Mutation {
addUsers(new_users: [UserInput]): [User]
#resolver(name: "add_users", paginated: false)
}
How do create a FaunaDB role in such a way that all of the users (except the current one) in resulting array from allUsers query, will not have email field?
I could break User collection into two: one is public, the other is accessible to a document owner, but this sounds wrong.
I'm new to the noSQL concept, so maybe I'm looking at this problem from the wrong perspective?
it's a request that came up a few times. You probably want to do this straight in FaunaDB's ABAC role system but although it provides row-level security, hiding a specific field is currently not provided yet. The feedback has been logged though, we will look into it.
The current way to do this is to split out Users from Accounts and fetch Users instead of Accounts. It would be useful to have something like hidden fields though in the future.
If you think of it, in this case, it does make sense to split authentication information from User information. You never know that you might offer another way to authentication in the future. I still recall from the Phoenix Framework book that they do it there was well and considered it a good practice.
You could also make a thin wrapper using Apollo in a serverless function and filter out these fields when you pass through the results. There is a guide that explains how to build such a thin Apollo middleware that just delegates to FaunaDB https://www.gatlin.io/blog/post/social-login-with-faunadb-and-auth0

Get rule list in zend acl

I'm working with zend framework 2. In there I can Get resource list of acl as getResources();
like this method how to get rule list in the acl in zend framework 2?
Looking at the Acl.php file in ZF2 repository in Github, I guess you should be able to call the function below to get the list of rules associated with a Resource and a Role:
protected function &getRules(Resource\ResourceInterface $resource = null, Role\RoleInterface $role = null, $create = false)
{
}
This is what they have written above the function:
Returns the rules associated with a Resource and a Role, or null if no such rules exist
If either $resource or $role is null, this means that the rules returned are for all Resources or all Roles, respectively. Both can be null to return the default rule set for all Resources and all Roles.
If the $create parameter is true, then a rule set is first created and then returned to the caller.
However, although it's not clear what you want to achieve here, I personally don't find it a good idea to work with the list of rules. You should only play with the roles and let the system take care of the rules. For example in ZF2, as mentioned in their documentation:
Roles can inherit from other existing roles without having to be assigned with some rules directly.
You can read more about the roles in ZF2 and how to implement them here.

Joining entities with #ManyToMany relationship

I have these entities:
User
Role
Permission
A user has many roles and a role has many permissions.
What is the best way to retrieve a set of permission a user has?
I need a method to check if a User has a particular Permission.
This is what I have so far:
public boolean hasPermission(String permissionString) {
if (!authenticated) return false;
for (Role role : user.getRoles()) {
for (Permission permission : role.getPermissions()) {
if (permission.getName().equals(permissionString)) {
return true;
}
}
}
return false;
}
A second, but related question -- where should I put the code that checks if a user has a particular permission?
In the User entity?
In the UserBean EJB?
In the Authentication JSF Managed Bean?
It depends on your mappings, the number of objects in the list, if the lists have already been fetched, your database connections, the database tuning etc.
You would have to try with production data to determine what ways are best.
For instance, If your collections have been prefetched with a join query, then traversing them in Java is trivial. If they haven't, each access in the for loop would cause a query to populate the objects. If it is the last one all the time, it means your java code causes you to traverse your object graph in the worst way possible and it would have been better to fetch it upfront. So you would be losing any benefit of lazy access, and would be better of hitting the database once to query for the permission linked to this user with the permissionString name: "Select p from u User join u.roles r join r.permissions p where p.name = :permissionName".
Only testing on production data will give you the best answer for your situation, and numerous other decisions in the application and mappings change the outcome.