Architecture > Authentication
Data Filter
Overview
This plugin control at a granular level what data a user can see. Here are the steps:
-
A user is successfully logged in, determined by com.f1.ami.web.auth.AmiAuthenticator
plugin which can return as set of variables that are assigned to the user's session (these variables often come from some external corporate entitlements system).
-
This user-session is passed into the com.f1.ami.web.datafilter.AmiWebDataFilterPlugin
which then returns a com.f1.ami.web.datafilter.AmiWebDataFilterinstance
. Note that each user will generally have there "own" AmiWebDataFilter assigned to there session.
-
As data is passed from the backend to the frontend its is first visited by the user's AmiWebDataFilter where the DataFilter can choose to suppress the data or not. There are two distinct ways data can be transferred from the "backend" to the user:
-
Realtime - As data is streamed into AMI, individual records are transported to the front end for display on a per-row basis. More specifically as rows are added(1), updated(2) and deleted from the backend a corresponding message is sent to the frontend.
- See
AmiWebDataFilter::evaluateNewRow(...)
- See
AmiWebDataFilter::evaluateUpdateRow(...)
(Note, that deletes do not have a callback as it is not applicable for data filtering)
-
Query results - when the user invokes a query (generally via the EXECUTE command within a datamodel) a query object is constructed and sent back to the back end for execution(1). Then, the backend responds with a table (or multiple tables) of data(2).
- See
AmiWebDataFilter::evaluateQueryRequest(...)
- See
AmiWebDataFilter::evaluateQueryResponse(...)
Java interface
| com.f1.ami.web.datafilter.AmiWebDataFilterPlugin
com.f1.ami.web.datafilter.AmiWebDataFilter
|
Properties
| ami.web.data.filter.plugin.class=fully_qualified_class_name
|
Example
See below for the configuration, make sure this matches the package and class names used in the data filter plugin java file.
| ami.web.data.filter.plugin.class=com.mysamples.SampleDataFilterPlugin
|
See below for the plugin java code, this describes what the plugin should do when a user logs in and logs out e.g. querying an external database to see what groups a user should have permission for.
| package com.mysamples;
import com.f1.ami.web.datafilter.AmiWebDataFilter;
import com.f1.ami.web.datafilter.AmiWebDataFilterPlugin;
import com.f1.ami.web.datafilter.AmiWebDataSession;
import com.f1.container.ContainerTools;
import com.f1.utils.PropertyController;
public class SampleDataFilterPlugin implements AmiWebDataFilterPlugin {
@Override
public void init(ContainerTools tools, PropertyController props) {
}
@Override
public String getPluginId() {
return "DATAFILTER_PLUGIN";
}
@Override
public void onLogin() {
//Code to implement when the user logs in;
}
@Override
public void onLogout() {
//Code to implement when the user logs out;
}
@Override
public AmiWebDataFilter createDataFilter(AmiWebDataSession session) {
return new SampleDataFilter(session);
}
}
|
See below for the filter java code, this describes how realtime feeds should be filtered (using evaluateNewRow
and evaluateUpdatedRow
) and how EXECUTE
queries in datamodels should be filtered (using evaluateQueryRequest
and evaluateQueryResponse
).
| package com.mysamples;
import com.f1.ami.web.AmiWebObject;
import com.f1.ami.web.datafilter.AmiWebDataFilter;
import com.f1.ami.web.datafilter.AmiWebDataFilterQuery;
import com.f1.ami.web.datafilter.AmiWebDataSession;
import com.f1.base.Column;
import com.f1.base.Row;
import com.f1.utils.structs.table.columnar.ColumnarTable;
public class SampleDataFilter implements AmiWebDataFilter {
private AmiWebDataSession userSession;
private String allowedRegion;
public SampleDataFilter(AmiWebDataSession session) {
this.userSession = session;
allowedRegion = (String) userSession.getVariableValue("region");
if(allowedRegion==null)
throw new RuntimeException("no 'region' specified");
}
@Override
public byte evaluateNewRow(AmiWebObject realtimeRow) {
String region = (String) realtimeRow.getParam("region");
return allowedRegion.equals(region) ? SHOW_ALWAYS : HIDE_ALWAYS;
}
@Override
public byte evaluateUpdatedRow(AmiWebObject realtimeRow, byte currentStatus) {
Object region = (String) realtimeRow.getParam("region");
return allowedRegion.equals(region) ? SHOW_ALWAYS : HIDE_ALWAYS;
}
@Override
public AmiWebDataFilterQuery evaluateQueryRequest(AmiWebDataFilterQuery query) {
return query;
}
@Override
public void evaluateQueryResponse(AmiWebDataFilterQuery query, ColumnarTable table) {
Column regionColumn = table.getColumnsMap().get("region");
if (regionColumn == null)
return;
for (int i = table.getSize() - 1; i >= 0; i--) {
Row row = table.getRow(i);
String region = row.getAt(regionColumn.getLocation(), String.class);
if (!allowedRegion.equals(region))
table.removeRow(row);
}
}
}
|