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 <u...@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-unsubscr...@tapestry.apache.org
>> For additional commands, e-mail: users-h...@tapestry.apache.org
>>
>>
> 


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

Reply via email to