You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Ulrich Stärk <ul...@spielviel.de> on 2012/10/30 20:44:29 UTC

injecting the currently logged in user

>From a third-party module (tynamo-security) I have the id (principal) of a Hibernate entity
representing the currently logged in user in the HttpSession. I now want to inject that user into
pages after loading it from persistent storage. The entity class shall be called User.

Three options come to my mind:

1. Wrap the entity in another class, e.g. CurrentUser, which takes a Hibernate session and has a
getUser() accessor which retrieves the User object from persistent storage. Store CurrentUser as a
Session State Object and inject it using @SessionState. Needs an ApplicationStateCreator. Downside:
needs an additional call to currentUser.getUser() every time I want to access the actual logged in user.

2. Create a UserSource service that looks up the User instance, build a PropertyShadowBuilder around
it and bind it to the interface of the User class. Downside: requires the User entity to have an
interface.

3. Create a persistence strategy that uses the principal from the http session to restore the User
from persistent storage. Similar to @Persist("entity").

The goal is to just @Inject User currentUser; or @SessionState User currentUser; or @Persist User
currentUser; in a page or service and have acces to the user as denoted by the principal stored in
the http session. Which option would you chose? Are there others, maybe more straightforward ones,
that I'm missing?

Cheers,

Uli

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: injecting the currently logged in user

Posted by Ulrich Stärk <ul...@spielviel.de>.
On 30.10.2012 21:11, Ulrich Stärk wrote:
> On 30.10.2012 21:05, Thiago H de Paula Figueiredo wrote:
>> On Tue, 30 Oct 2012 17:44:29 -0200, Ulrich Stärk <ul...@spielviel.de> wrote:
>>
>>> 2. Create a UserSource service that looks up the User instance, build a PropertyShadowBuilder
>>> around it and bind it to the interface of the User class. Downside: requires the User entity to
>>> have an interface.
>>
>> Why don't you implement a InjectionProvider that uses the UserSource to get the current logged user?
>> This way, you can @Inject private User user;.
>>
> 
> Too obvious I suppose. Sometimes you can't see the most obvious solution, thanks for the pointer.
> 
> Uli
> 

Ok, it seems that the InjectionProvider is evaluated only once, the first time the class is
transformed. This doesn't work in my case since on first load, the logged in user is always null.

Uli

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: injecting the currently logged in user

Posted by Ulrich Stärk <ul...@spielviel.de>.
On 30.10.2012 21:05, Thiago H de Paula Figueiredo wrote:
> On Tue, 30 Oct 2012 17:44:29 -0200, Ulrich Stärk <ul...@spielviel.de> wrote:
> 
>> 2. Create a UserSource service that looks up the User instance, build a PropertyShadowBuilder
>> around it and bind it to the interface of the User class. Downside: requires the User entity to
>> have an interface.
> 
> Why don't you implement a InjectionProvider that uses the UserSource to get the current logged user?
> This way, you can @Inject private User user;.
> 

Too obvious I suppose. Sometimes you can't see the most obvious solution, thanks for the pointer.

Uli

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: injecting the currently logged in user

Posted by Thiago H de Paula Figueiredo <th...@gmail.com>.
On Tue, 30 Oct 2012 17:44:29 -0200, Ulrich Stärk <ul...@spielviel.de> wrote:

> 2. Create a UserSource service that looks up the User instance, build a  
> PropertyShadowBuilder around it and bind it to the interface of the User  
> class. Downside: requires the User entity to have an interface.

Why don't you implement a InjectionProvider that uses the UserSource to  
get the current logged user? This way, you can @Inject private User user;.

-- 
Thiago H. de Paula Figueiredo

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: injecting the currently logged in user

Posted by Ulrich Stärk <ul...@spielviel.de>.
I played around with a few of the options I outlined and in the end chose the FieldConduit approach
that Lenny suggested.

The base is a service called CurrentUserSource which has a single method getUser() that does

if(!securityService.isAuthenticated())
    return null;
Long id = (Long) securityService.getSubject().getPrincipal();
return (User) session.load(User.class, id);

with securityService being tynamo-security's wrapper around Shiro's SecurityUtils and session being
the Hibernate Session object from tapestry-hibernate.

The FieldConduit setup consists of an annotation called CurrentUser and a
ComponentClassTransformWorker2 called CurrentUserWorker:

public class CurrentUserWorker implements ComponentClassTransformWorker2
{
    class CurrentUserFieldConduit implements FieldConduit<User>
    {
        public User get(Object instance, InstanceContext context)
        {
            return currentUserSource.getUser();
        }

        public void set(Object instance, InstanceContext context, User newValue)
        {
            // TODO merge changes back to persistent storage?
        }
    }

    private final CurrentUserSource currentUserSource;

    public CurrentUserWorker(CurrentUserSource currentUserSource)
    {
        this.currentUserSource = currentUserSource;
    }

    public void transform(PlasticClass plasticClass, TransformationSupport support,
            MutableComponentModel model)
    {
        // wire field to field conduit
        for (PlasticField field : plasticClass.getFieldsWithAnnotation(CurrentUser.class))
        {
            CurrentUser annotation = field.getAnnotation(CurrentUser.class);

            field.claim(annotation);

            ComputedValue<FieldConduit<User>> computed = new ComputedValue<FieldConduit<User>>()
            {

                public FieldConduit<User> get(InstanceContext context)
                {
                    return new CurrentUserFieldConduit();
                }
            };

            field.setComputedConduit(computed);
        }
    }
}

This is wired together in your module class using

@Contribute(ComponentClassTransformWorker2.class)
public void provideCurrentUserTransformWorker(
        OrderedConfiguration<ComponentClassTransformWorker2> configuration)
{
    configuration.addInstance("CurrentUser", CurrentUserWorker.class);
}

In a page or component you can now simply write

@CurrentUser
private User currentUser;

and have access to the currently logged in user.

Oh, and the main requirement is that you use the user's id attribute as used by Hibernate as the
principal.

Cheers,

Uli

On 02.11.2012 02:20, Alex Kotchnev wrote:
> Ulrich - I'll be curious to see what you come up with. I also use Shiro and
> have the user stored in the database, and have been thinking that I need to
> have a better way of having access to the current user (e.g. using some
> annotation). I'm not entirely sure how this FieldConduit would work (what
> Lenny suggested).
> 
> Cheers - Alex K
> 
> 
> On Wed, Oct 31, 2012 at 6:42 PM, Ulrich Stärk <ul...@spielviel.de> wrote:
> 
>> On 31.10.2012 17:28, Lenny Primak wrote:
>>> The Principal is already saved by Shiro in the HttpSession,
>>
>> Exactly what I said.
>>
>>> why just not use a custom annotation with a FieldConduit
>>> that just gets it from Tynamo-security SecurityService?
>>
>> Because I haven't thought of that yet, thanks for the suggestion. Although
>> in my case it would
>> require loading the entity represented by the principal from persistent
>> storage so SecurityService
>> alone wouldn't be sufficient.
>>
>> Cheers,
>>
>> Uli
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
>> For additional commands, e-mail: users-help@tapestry.apache.org
>>
>>
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: injecting the currently logged in user

Posted by Alex Kotchnev <ak...@gmail.com>.
Ulrich - I'll be curious to see what you come up with. I also use Shiro and
have the user stored in the database, and have been thinking that I need to
have a better way of having access to the current user (e.g. using some
annotation). I'm not entirely sure how this FieldConduit would work (what
Lenny suggested).

Cheers - Alex K


On Wed, Oct 31, 2012 at 6:42 PM, Ulrich Stärk <ul...@spielviel.de> wrote:

> On 31.10.2012 17:28, Lenny Primak wrote:
> > The Principal is already saved by Shiro in the HttpSession,
>
> Exactly what I said.
>
> > why just not use a custom annotation with a FieldConduit
> > that just gets it from Tynamo-security SecurityService?
>
> Because I haven't thought of that yet, thanks for the suggestion. Although
> in my case it would
> require loading the entity represented by the principal from persistent
> storage so SecurityService
> alone wouldn't be sufficient.
>
> Cheers,
>
> Uli
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
>
>

Re: injecting the currently logged in user

Posted by Ulrich Stärk <ul...@spielviel.de>.
On 31.10.2012 17:28, Lenny Primak wrote:
> The Principal is already saved by Shiro in the HttpSession,

Exactly what I said.

> why just not use a custom annotation with a FieldConduit
> that just gets it from Tynamo-security SecurityService?

Because I haven't thought of that yet, thanks for the suggestion. Although in my case it would
require loading the entity represented by the principal from persistent storage so SecurityService
alone wouldn't be sufficient.

Cheers,

Uli

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org


Re: injecting the currently logged in user

Posted by Lenny Primak <lp...@aceinnovative.com>.
The Principal is already saved by Shiro in the HttpSession,
why just not use a custom annotation with a FieldConduit
that just gets it from Tynamo-security SecurityService?

On Oct 30, 2012, at 3:44 PM, Ulrich Stärk <ul...@spielviel.de> wrote:

> From a third-party module (tynamo-security) I have the id (principal) of a Hibernate entity
> representing the currently logged in user in the HttpSession. I now want to inject that user into
> pages after loading it from persistent storage. The entity class shall be called User.
> 
> Three options come to my mind:
> 
> 1. Wrap the entity in another class, e.g. CurrentUser, which takes a Hibernate session and has a
> getUser() accessor which retrieves the User object from persistent storage. Store CurrentUser as a
> Session State Object and inject it using @SessionState. Needs an ApplicationStateCreator. Downside:
> needs an additional call to currentUser.getUser() every time I want to access the actual logged in user.
> 
> 2. Create a UserSource service that looks up the User instance, build a PropertyShadowBuilder around
> it and bind it to the interface of the User class. Downside: requires the User entity to have an
> interface.
> 
> 3. Create a persistence strategy that uses the principal from the http session to restore the User
> from persistent storage. Similar to @Persist("entity").
> 
> The goal is to just @Inject User currentUser; or @SessionState User currentUser; or @Persist User
> currentUser; in a page or service and have acces to the user as denoted by the principal stored in
> the http session. Which option would you chose? Are there others, maybe more straightforward ones,
> that I'm missing?
> 
> Cheers,
> 
> Uli
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
> For additional commands, e-mail: users-help@tapestry.apache.org
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org