Customize Application layout by user roles
- Different application layout based on given user roles
- repeatedly requested by enterprise RCP app developers
Different menu bars, window layout, toolbars based on user role
Solution #1: control by module
- each role owns unique module which contains application UI specific to role
- only one such module can be active
- needs "exclusivity" mode in module system, i.e. module A, module B. If A and B are "exclusive", then only one of them can be active at the same time
Solution #2: control by SFS paths
- a control module filtering object from SFS by given roles
- nice to have new tooling in apisupport
- similarities to ImprovedBrandingSupport69
Solution #3: declarative control by module
I (Florian Brunner) want to propose a third solution:
- One module can be used by several roles (read the list as 'OR', not 'AND')
- One role can be required by several modules
- Define an interface, which provides a set of roles and a way to listen for changes to that set (eg. via Lookup?)
- Enhance the module system:
- No module with 'OpenIDE-Module-Requires-Roles' (or similar) is loaded by default
- For each module, which provides an implementation of this new interface (OpenIDE-Module-Provides?), the module system registers a listener to listen for changes in the set of roles
- On start and on change event, the module system gets the set of roles
- For each module with 'OpenIDE-Module-Requires-Roles' the module system checks:
- If there is an intersection of the set of roles specified in the Manifest with the set of roles from the roles provider and if the module is not loaded yet -> load it
- If there is no intersection but the module is already loaded -> unload it
- Unlike enabled/ disabled module state, this state is not persistent
Statement of solution #1 is too narrow; people frequently request that certain GUI elements be available only after authentication. A given user may have any combination of roles, hence modules, so exclusivity is the wrong approach; just want to pick which modules to enable according to some arbitrary logic included in a startup module. A clearer statement of what is needed is that some modules should have no persisted enablement state - they should be initially disabled upon every startup, and enabled for the remainder of the session according to some programmatic call. Needs some cooperation with Plugin Manager (to disable Activate/Deactivate buttons).
Solution #2 is perhaps safer - manipulation of the SFS is likely to be more reliable than turning modules on and off. (Though it is not clear #1 ever requires a module to be disabled; enabling is fairly reliable.) It is more flexible in the sense that you need not rely on module granularity, but for the same reason might be less intuitive. Two possible variants:
- Some config file which activates or deactivates various paths (or path regexps?) in the SFS according to role. Pros: little change to regular module development until you activate role management. Cons: requires separate config file in a novel format (tricky to integrate with tooling); requires changes to NB core.
- Merge Roles/<rolename>/ folder into SFS whenever <rolename> is activated. Pros: simple concept; can be implemented in an experimental module today (e.g. contrib/profiles). Cons: XML layer tooling could be confused by the merged dirs; will not work correctly with layer-generating annotations.
Solution #3 is very flexible and very powerful, I think.
- Eg. consider a remote EJB service 'Foo', for which the role 'hr' has read access and the role 'manager' has read and write access. With this solution you can group the GUI for reading from this service to one module and the extensions to provide writing functionality to another module. You can do this for any combinations of services and roles.
- A module is a 'natural' unit for something like this in the NetBeans Platform world
- The module system can detect how to handle the modules just by reading the Manifest files
Situations when the set of roles changes:
- successful login
- successful relogin with different user
- admin adds another role to an user/ group
- admin removes a role from an user/ group
Note: IMHO, it's very important that the implementation supports fixed modules! Reason: a NetBeans Platform application in JNLP-mode uses fixed modules by default, but JNLP is very common for Java EE remote clients.
Restricted parts of application only for some roles
- a transient module which must be downloaded from inet at the start of each session and removed at the end
- needs changes in NetBeans Module Systems
- loading a module just from memory, don't save to disk
Again this is the wrong statement of the problem. Modules can already be downloaded on demand using the Auto Update Services API, and you want them to be stored in the installation and updated when new versions are available etc. (In JNLP mode, they would just be part of the JNLP descriptor - caching and versioning are automatic.) What is needed is for their enablement to be controlled by core application code rather than static configuration.
Data access restricted only for some roles
This should be managed by other systems. The Java platform already contains a sophisticated authentication & authorization system, and there are other third-party systems.
It is important to remember that the list of modules to activate based on authenticated role controls what GUI is presented but has no meaning from the perspective of security. Any security-sensitive operation must be guarded by an authorization object, regardless of which module initiated it. This is nearly meaningless for local operations (since you could download & run any modules you found or wrote and they will run with full permissions); for server operations, the server would be expected to authorize each transaction.
- UI: login window/access rights
- new SPI for authentication like isAuthenticated, getRole
- some workarounds: DevFaqPlatformAppAuthStrategies