la-team / light-admin

[PoC] Pluggable CRUD UI library for Java web applications
http://lightadmin.org
Apache License 2.0
664 stars 255 forks source link

Fine grained control of displaying/hiding fields #152

Open mnrasul opened 9 years ago

mnrasul commented 9 years ago

I'm looking for a way to have fine grained authorization. Show/hide fields in views based on a criteria.

Here there could be two possibilities.

Control access to all views as a group: We could decide that a particular role does not have "authorization" to view fields b, c ,e, however they can view fields a,d,f.

We could argue that this restriction applies on all views i.e list, individual detail view, searches ....

Control access to each view individually Another argument could be that we would need fine grained access to each view separately if needed, or applied in a group by default.

Probably first is sufficient. I am not certain if second has real world value. Second is more flexible, but might be more difficult too.

max-dev commented 9 years ago

Thanks mate :+1:

max-dev commented 9 years ago

Here is a draft implementation provided as an example for customization:

    private static interface EnhancedFieldSetConfigurationUnitBuilder extends FieldSetConfigurationUnitBuilder {

        EnhancedFieldSetConfigurationUnitBuilder field(String fieldName);

        EnhancedFieldSetConfigurationUnitBuilder caption(String caption);

        EnhancedFieldSetConfigurationUnitBuilder dynamic(String expression);

        EnhancedFieldSetConfigurationUnitBuilder renderable(FieldValueRenderer<?> renderer);

        EnhancedFieldSetConfigurationUnitBuilder enumeration(EnumElement... elements);

        EnhancedFieldSetConfigurationUnitBuilder visible(Predicate<FieldMetadata> fieldVisibilityPredicate);
    }

    private static class MyEnhancedFieldSetConfigurationUnitBuilder implements EnhancedFieldSetConfigurationUnitBuilder {

        private final FieldSetConfigurationUnitBuilder delegate;
        private final PropertyAccessor delegatePropertyAccessor;

        private MyEnhancedFieldSetConfigurationUnitBuilder(FieldSetConfigurationUnitBuilder delegate) {
            this.delegate = delegate;
            this.delegatePropertyAccessor = PropertyAccessorFactory.forDirectFieldAccess(this.delegate);
        }

        public static EnhancedFieldSetConfigurationUnitBuilder wrap(FieldSetConfigurationUnitBuilder builder) {
            return new MyEnhancedFieldSetConfigurationUnitBuilder(builder);
        }

        @Override
        public EnhancedFieldSetConfigurationUnitBuilder field(String fieldName) {
            delegate.field(fieldName);
            return this;
        }

        @Override
        public EnhancedFieldSetConfigurationUnitBuilder caption(String caption) {
            delegate.caption(caption);
            return this;
        }

        @Override
        public EnhancedFieldSetConfigurationUnitBuilder dynamic(String expression) {
            delegate.dynamic(expression);
            return this;
        }

        @Override
        public EnhancedFieldSetConfigurationUnitBuilder renderable(FieldValueRenderer<?> renderer) {
            delegate.renderable(renderer);
            return this;
        }

        @Override
        public EnhancedFieldSetConfigurationUnitBuilder enumeration(EnumElement... elements) {
            delegate.enumeration(elements);
            return this;
        }

        @Override
        public FieldSetConfigurationUnit build() {
            return delegate.build();
        }

        private FieldMetadata currentField() {
            return (FieldMetadata) delegatePropertyAccessor.getPropertyValue("currentFieldMetadata");
        }

        public EnhancedFieldSetConfigurationUnitBuilder visible(Predicate<FieldMetadata> fieldVisibilityPredicate) {
            Assert.notNull(currentField());
            if (!fieldVisibilityPredicate.apply(currentField())) {
                delegatePropertyAccessor.setPropertyValue("currentFieldMetadata", null);
            }
            return this;
        }
    }

And usage in Administration configuration:

    public FieldSetConfigurationUnit showView(final FieldSetConfigurationUnitBuilder fragmentBuilder) {
        return MyEnhancedFieldSetConfigurationUnitBuilder.wrap(fragmentBuilder)
                .field("avatar").caption("Avatar")
                .field("registrationDate").caption("Registration Date").visible(fieldVisibilityPredicate())
                .build();
   }

    private Predicate<FieldMetadata> fieldVisibilityPredicate() {
        return new Predicate<FieldMetadata>() {
            @Override
            public boolean apply(FieldMetadata field) {
                String fieldName = field.getName();
                boolean visibilityCondition = "name".equals(fieldName);

                return visibilityCondition;
            }
        };
    }
Pinny3 commented 9 years ago

Looks nice. When will it be available in the Snapshot Release?

jimmyfm commented 9 years ago

This smells like a possible solution for #157 , i'll lok better into it.