Arrays of enums in security meta annotations have limited utility because there's no clean mechanism to convert the enum to a custom value.
If I have an enum that specifies my permissions, such as:
enum Permission {
READ("permission.read"),
WRITE("permission.write");
private final value;
// constructor implementation
@Override
public String toString() {
return value;
}
}
I cannot have a working meta annotation with an array of enums such as the following:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@PreAuthorize("hasAnyAuthority({permissions})")
@interface HasAnyPermission {
Permission[] permissions();
}
The ExpressionTemplateSecurityAnnotationScanner.conversionService
includes EnumToStringConverter
that will always use Enum.name()
instead of my overridden toString()
method.
Modifying the static conversionService
initializer in ExpressionTemplateSecurityAnnotationScanner
to:
static {
conversionService.addConverter(new ClassToStringConverter());
conversionService.removeConvertible(Enum.class, String.class);
}
corrects the issue.
Since the default Enum.toString()
returns the enum's name, removing the explicit Enum converter would be backwards compatible for most code. I'm sure there's a more clever solution that ensures backwards compatibility.