-
1. Re: How to combine s:viewAction and Seam 3 Security
zeeman Mar 6, 2012 12:06 AM (in response to lukascz)I don't use @RestrictPhase on enum. On your @Leader annotation use phase there:
@SecurityBindingType
@RestrictAtPhase(PhaseIdType.RESTORE_VIEW)
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.TYPE })
public @interface Leader{
}
For me restore_view works well on security annotation. Be sure to use correct on xhtml.
-
2. Re: How to combine s:viewAction and Seam 3 Security
lukascz Mar 6, 2012 3:37 PM (in response to zeeman)The problem is that RESTORE_VIEW happens before APPLY_REQUEST_VALUES when the s:viewAction is executed. And I need to execute the view action before the security check happens
-
3. Re: How to combine s:viewAction and Seam 3 Security
lightguard Mar 7, 2012 4:47 PM (in response to lukascz)That's a tough one. You could try the RestrictAtPhase for a different phase and see if that works for you. That's the best I've got, sorry.
-
4. Re: How to combine s:viewAction and Seam 3 Security
lukascz Mar 7, 2012 5:11 PM (in response to lightguard)That didn't work for me.
I solved it in following way:
@Secures @Leader
public boolean isLeader(Identity identity, @HttpParam("entryId") Entry entry)
....
Where Entry is injected using GET parameter entryId
I don't like this solution, because now the GET parameters is used twice in different places (HttpParam and viewAction) and I need to load the entity twice. But it works
-
5. Re: How to combine s:viewAction and Seam 3 Security
jluv Mar 19, 2012 12:20 AM (in response to lukascz)I struggled with this for hours, and finally got it working through trial and error. First, it's very counterintuitive, but you have to set @RestrictAtPhase(PhaseIdType.RESTORE_VIEW) on your SecurityBindingType enum. Nothing else works for this scenario.
Second, you don't have to mess around with s:action or trying to pass in the HTTP request paramter to your authorizer method. Seam 3 Solder now has the @RequestParam annotation that you can use to just inject your parameter value.
If your CDI bean is RequestScoped:
{code}
@Inject
@RequestParam
private String id;
{code}
If your CDI bean has a scope wider than RequestScoped:
{code}
@Inject
@RequestParam("id")
private Instance<String> idResolver;
{code}
Then add a PostConstruct method to do whatever you need to do. For example:
{code}
@PostConstruct
public void postConstruct() {
String id = idResolver.get();
meter = entityManager.find(Meter.class, Integer.valueOf(id));
if (meter == null) {
messenger.error(meterNotFoundMessageKey, id);
}
}
{code}
Here's my SecurityBindingType enum:
{code}
@SecurityBindingType
@RestrictAtPhase(PhaseIdType.RESTORE_VIEW)
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
public @interface MeterOwner {
}
{code}
And my authorizer method, which gets called twice when the page is requested:
{code}
public @Secures @MeterOwner boolean isOwner(MeterView meterView) {
if (meterView == null || identity.getUser() == null) {
return false;
} else {
if (meterView.getMeter() == null) return false; // meter is null on first invocation
String ownerId = meterView.getMeter().getUser().getId();
return identity.getUser().getId().equals(ownerId);
}
}
{code}