-
1. Re: How to get the authenticated user in Drools
stefanotravelli Dec 31, 2008 11:25 AM (in response to jagin)Declare your session-scoped object as a global variable in the rule using the name of the object as the variable name.
This doesn't put your object in the working memory, but you can write a rule that accesses it and make an insert(), if needed.
stefano
-
2. Re: How to get the authenticated user in Drools
jagin Jan 1, 2009 4:53 PM (in response to jagin)Hi Stefano,
i'm new to Drools and its concept is still a bit fuzzy form me.
Could you provide an examle of declaring global variabe using session object?Thanks
Jarek
-
3. Re: How to get the authenticated user in Drools
stefanotravelli Jan 2, 2009 2:39 PM (in response to jagin)Drools has the concept of
global variables
. It's well defined in the Drools documentation, but the basic is that this variables are set to some value when the working memory is created.With the Seam Drools integration usually you don't create working memories because they are managed by the RuleBase (or the RuleAgent) component.
However Seam managed working memories come with a special GlobalResolver (see org.jboss.seam.drools.SeamGlobalResolver) that
resolves seam context variables as Drools globals
(from Javadoc).So you simply declare the global:
package mypackage import com.something.User global User loggedUser rule "check logged user" dialect "mvel" when eval(loggedUser.name == "stefano") then ... do something end
The global variable loggedUser will be resolved from Seam contexts, just like when you type @In(value = "loggedUser") in a regular Java class.
-
4. Re: How to get the authenticated user in Drools
jagin Jan 5, 2009 3:12 PM (in response to jagin)Hi Stefano,
Thanks a lot for the hint. But still I have some problems.
I have rool like this
package Permissions; import java.security.Principal; import org.jboss.seam.security.permission.PermissionCheck; import org.jboss.seam.security.Role; import pl.unizeto.webrbe.model.User; global pl.unizeto.webrbe.model.User loggedUser; rule UserList no-loop dialect "mvel" when perm: PermissionCheck(name == "user", action == "list", granted == false) //eval("USER" memberOf loggedUser.dataAccessTypes) //eval(loggedUser.username == "admin") eval(true); then System.out.println("DEBUG - loggedUser = " + loggedUser); // for debug perm.grant();
end
loggedUser has a factory like this
@Factory(value = "loggedUser", autoCreate = true) public User getLoggedUser() { ... }
UserList.page.xml has restriction like
<restrict>#{s:hasPermission('user', 'list')}</restrict>
but loggedUser is always null. After going to UserList.xhtml page i got
DEBUG - loggedUser = null
Why? Is there something i missed??
Uncomenting
eval(loggedUser.username == "admin")
couse
Exception during request processing: Caused by javax.el.ELException with message: "org.drools.RuntimeDroolsException: org.mvel.CompileException: unable to resolve property: username"
but it's perhapse of loogedUser been null
Regards
Jarek
-
5. Re: How to get the authenticated user in Drools
stefanotravelli Jan 5, 2009 5:43 PM (in response to jagin)You are right. My fault.
SeamGlobalResolver is not used by RuleBasedPermissionResolver, so the global variable is not resolved.
It would seem reasonable to me to use SeamGlobalResolver even in the RuleBasedPermissionResolver as it is in ManagedWorkingMemory. Maybe we should ask for such a feature to the Seam team.
In the meanwhile you can get your component from the Seam contexts using a function. Something like:
package Permissions; import java.security.Principal; import org.jboss.seam.security.permission.PermissionCheck; import org.jboss.seam.security.Role; import pl.unizeto.webrbe.model.User; import org.jboss.seam.Component; global pl.unizeto.webrbe.model.User loggedUser; function boolean isAdmin() { User loggedUser = Component.getInstance("loggedUser", true); return "admin".equals(loggedUser.getUsername()); } rule UserList no-loop dialect "mvel" when perm: PermissionCheck(name == "user", action == "list", granted == false) //eval("USER" memberOf loggedUser.dataAccessTypes) eval(isAdmin()) //eval(true); then System.out.println("DEBUG - loggedUser = " + loggedUser); // for debug perm.grant();
However, I assume this is only a sample. If your use case really need only the user name, then you can get it from the Principal that is inserted in the working memory together with all the Roles of the current user.
rule "r" when principal: Principal(name == "admin") perm: PermissionCheck(name == "user", action == "list", granted == false) then perm.grant(); end
stefano
-
6. Re: How to get the authenticated user in Drools
jagin Jan 6, 2009 8:34 AM (in response to jagin)Thanks Stefano. You helped me a lot.
I created the JIRA issue for this: https://jira.jboss.org/jira/browse/JBSEAM-3877
Jarek
-
7. Re: How to get the authenticated user in Drools
jagin Jan 6, 2009 9:16 AM (in response to jagin)Stefano one more question if you mind:
How to write my own resolver to inject some context variables (for ex loggedUser :) ) into drools workin memory every time drools rools are checked?
Jarek
-
8. Re: How to get the authenticated user in Drools
jagin Jan 6, 2009 11:28 AM (in response to jagin)I think i found the solution.
In an authenticate() function of Autenticator component i've added:
... // put the logged user into drools working memory RuleBasedPermissionResolver resolver = RuleBasedPermissionResolver.instance(); if(resolver != null) { resolver.getSecurityContext().insert(user); } ...
and now rools is simple as
rule UserList no-loop dialect "mvel" when user: User() perm: PermissionCheck(name == "user", action == "list", granted == false) eval("USER" memberOf user.dataAccessTypes) then perm.grant(); end
That's it. Thanks again Stefano.
Jarek
-
9. Re: How to get the authenticated user in Drools
jagin Jan 7, 2009 8:40 AM (in response to jagin)The above solution is not the right way, becouse we can get 'lazy initialization' exception (user entity is disconnected from entitymanager).
I've done another trick which proves that using SeamGlobalResolver is RuleBasedPermissionResolver is the right way.
Fisrt: i copy SeamGlobalResolver.java source from SEAM to my application action package. I have to because SeamGlobalResolver class is private for org.jboss.seam.drools package.
Second: in Authenticator component i have added:
@Observer(Identity.EVENT_POST_AUTHENTICATE) public void setUserAccountInSecurityContext() { // Add Seam context variables resolver as Drools globals // Look here: http://www.seamframework.org/Community/HowToGetTheAuthenticatedUserInDrools // and here: https://jira.jboss.org/jira/browse/JBSEAM-3877 RuleBasedPermissionResolver resolver = RuleBasedPermissionResolver.instance(); resolver.getSecurityContext().setGlobalResolver( new SeamGlobalResolver(resolver.getSecurityContext().getGlobalResolver())); }
Now this rool (with global) is workin perfect:
package Permissions; import java.security.Principal; import org.jboss.seam.security.permission.PermissionCheck; import org.jboss.seam.security.Role; import org.jboss.seam.Component; import pl.unizeto.webrbe.model.User; import pl.unizeto.webrbe.model.DataAccessTypeEnum; global pl.unizeto.webrbe.model.User loggedUser; dialect "mvel" rule UserList no-loop when perm: PermissionCheck(name == "user", action == "list", granted == false) eval(loggedUser.dataAccessTypes contains DataAccessTypeEnum.USER) //for dialect "java" (default) it should be //eval(loggedUser.getDataAccessTypes().contains(DataAccessTypeEnum.USER)) then perm.grant(); end
Jarek
-
10. Re: How to get the authenticated user in Drools
gabrielsr Nov 17, 2010 7:37 AM (in response to jagin)Thanks, with the issue was correct in Seam 2.1, now you can just insert a user into the context:
public boolean authenticate() {
... Contexts.getSessionContext().set(usuarioLogado
, usuario);
}and take it with a global var in drools:
global br.com.esec.licenca.model.Usuario usuarioLogado;
- )