Emond Papegaaij created WICKET-7200:
---------------------------------------
Summary: Align class-vs-package resolution across the
wicket-auth-roles annotations
Key: WICKET-7200
URL: https://issues.apache.org/jira/browse/WICKET-7200
Project: Wicket
Issue Type: Improvement
Components: wicket-auth-roles
Reporter: Emond Papegaaij
Fix For: 11.0.0
h3. Problem
{{AnnotationsRoleAuthorizationStrategy}} implements three different rules for
combining a class level annotation with a package level one, and none of them
are documented:
* {{@AuthorizeInstantiation}}: the class annotation replaces the package
annotation.
* {{@AuthorizeAction}}: the package annotation is never read at all, even
though the
annotation has declared {{ElementType.PACKAGE}} since February 2006. An
{{@AuthorizeAction}} in a {{package-info.java}} compiles, looks correct, and
protects
nothing.
* {{@AuthorizeResource}}: the class annotation and the package annotation are
AND-ed.
* {{@AuthorizeInstantiations}}: the ruleset is AND-ed on unconditionally and
never
participates in the override, and it is class level only.
Two consequences that users hit in practice:
# Because these annotations are {{@Inherited}} and the class lookup runs first,
an
annotation on a superclass in _any_ package counts as the class level
annotation and
therefore suppresses the package level annotation of the subclass' own package.
Moving a page into a package guarded by {{package-info.java}} has no effect
when one
of its superclasses is annotated:
{code:java}
// org/mycompany/base/SecuredPage.java
@AuthorizeInstantiation("USER")
public class SecuredPage extends WebPage {
}
// org/mycompany/admin/package-info.java
@AuthorizeInstantiation("ADMIN")
package org.mycompany.admin;
// org/mycompany/admin/ReportPage.java -- requires USER, not ADMIN
public class ReportPage extends SecuredPage {
}
{code}
# Package level {{@AuthorizeAction}} silently does nothing, so a package that
appears
to be render protected is not.
h3. Which rule is the intended one
The override rule used for instantiation is the deliberate one. It carried the
comment
"If roles are defined for the class, that overrides the package" from the
start, and
WICKET-3240 asked for conjunctive behaviour and was resolved by keeping the
override
and only short-circuiting the lookup, with the comment "Check class annotation
first
because it is more specific than package annotation".
The conjunction used for resources is not a design decision. WICKET-5749
introduced it
in Wicket 7.0.0 as {{class || package}} with a missing annotation counting as
"deny".
The follow-up commit "non-annotated resources should be allowed, not denied"
corrected
the missing-annotation case to "allow", which forced {{||}} to become {{&&}} in
the
same edit purely to keep the annotation functional. That commit message does not
mention class-vs-package composition at all, and the annotation's own javadoc
still
states that it "works analogously to AuthorizeInstantiation", which it does not.
h3. Proposed change
Standardise on the override rule: the rules on a class replace the rules on its
package, and rules at the same level are combined with AND. Document it on
{{AnnotationsRoleAuthorizationStrategy}}, on each annotation, and in the user
guide.
* {{@AuthorizeAction}} and {{@AuthorizeActions}}: honour package level
annotations,
resolved per action name, so a class level rule for {{ENABLE}} overrides only
the
package rule for {{ENABLE}} and the package rule for {{RENDER}} still applies.
{{@AuthorizeActions}} gains {{ElementType.PACKAGE}}, without which a package
cannot
express more than one action rule.
* {{@AuthorizeResource}}: the class level annotation replaces the package level
one
instead of being AND-ed with it. This also removes an unguarded
{{resourceClass.getPackage()}} dereference, unlike the guarded instantiation
path.
* {{@AuthorizeInstantiations}}: participates in the override like every other
rule,
and gains {{ElementType.PACKAGE}}.
h3. Compatibility
Two behaviour changes, both loosening, both affecting only applications that
annotate
a class _and_ its package:
* a resource annotated at both levels with different roles previously required
both
sets of roles, and now requires only the roles of the class;
* a class carrying only {{@AuthorizeInstantiations}} inside a package carrying
{{@AuthorizeInstantiation}} previously required both, and now requires only the
class
ruleset.
Package level {{@AuthorizeAction}} changes from no-op to enforced, which can
only
tighten authorization, and only for applications that already wrote an
annotation that
never worked.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)