Select Git revision
AuthPolicy.java
-
Robert Butora authoredRobert Butora authored
AuthPolicy.java 9.24 KiB
// external inputs:
// User data (name and list of groups)
// List of PublisherDid's as param to some app-function (multi-cutout, merge)
// Database connection (from Settings)
// For Non-authenticated requests two behaviours possible:
// A, setups with configured security: return only PUBLIC data
// B, setups wihtout need of security: access all data
// Currently B supported: Vlkb security filters will always set UsePrincipal.
// Security filters could reserve 'anonymous' user for non-authenticated requests, if needed.
// So missing UserPrincipal is interpreted as setup without security filters - full access allowed.
import java.util.logging.Logger;
import java.io.PrintWriter;
import java.security.Principal;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.Arrays;
import java.util.ListIterator;
public class AuthPolicy
{
private static final Logger LOGGER = Logger.getLogger(AuthPolicy.class.getName());
enum Access { PUBLIC_ONLY, PUBLIC_AND_AUTHORIZED_PRIVATE };
private Access access;
private String userName;
private String[] userGroups;
private boolean userGroupsValid;
private String dbConnUrl;
private String dbUserName;
private String dbPassword;
public AuthPolicy(String userName, String[] userGroups)
{
this.userName = userName;
this.userGroups = userGroups;
this.userGroupsValid = true;
access = Access.PUBLIC_AND_AUTHORIZED_PRIVATE;
LOGGER.finer("User [Groups]: " + userName + " [ " + String.join(" ", userGroups) + " ]" );
}
public AuthPolicy(Principal principal)
{
if(principal == null)
{
access = Access.PUBLIC_ONLY;
userName = null;
userGroups = null;
userGroupsValid = false;
LOGGER.finer("Non authenticated request (UserPrincipal null in HttpServletRequest)");
}
else
{
if(principal instanceof VlkbUser)
{
VlkbUser vlkbUser = (VlkbUser) principal;
userName = vlkbUser.getName();
userGroups = vlkbUser.getGroupsAsArray();
userGroupsValid = true;
access = Access.PUBLIC_AND_AUTHORIZED_PRIVATE;
LOGGER.finer("User [Groups]: " + userName + " [ " + String.join(" ", userGroups) + " ]" );
}
else
{
userName = principal.getName();
LOGGER.finer("DBG principal not instance of VlkbUser, but has user-name: " + userName);
userGroups = new String[]{""};//{"VLKB.groupA", "AllPrivate"}; // was for shiro
userGroupsValid = true;
access = Access.PUBLIC_AND_AUTHORIZED_PRIVATE;
//throw new IllegalArgumentException("UserPrincipal is not of expected type");
}
}
}
public String getUserName()
{
return userName;
}
public boolean getUserGroupsValid()
{
return userGroupsValid;
}
public String[] getUserGroups()
{
return userGroups;
}
public String getUserGroupsSqlFormat()
{
if( (userGroups != null) && (userGroups.length > 0) )
{
return "\"" + String.join("\",\"" , userGroups) + "\"";
}
else
{
return null;
}
}
public String getUserGroupsAsString(String separator)
{
if( (userGroups != null) && (userGroups.length > 0) )
{
return String.join(separator, userGroups);
}
else
{
return null;
}
}
public String getAccessPolicy()
{
return access.name(); // returns enum as string
}
public void toXML(PrintWriter writer)
{
writer.println("<AccessPolicy>" + this.getAccessPolicy() + "</AccessPolicy>");
String ug = getUserGroupsAsString(" ");
if(userName != null) writer.println("<UserName>" + userName + "</UserName>");
if(ug != null) writer.println("<GroupNames>" + ug + "</GroupNames>");
}
public String[] filterAuthorized(String[] pubdidArr, String dbConnUrl, String dbUserName, String dbPassword)
{
//this.dbConnUrl = dbConnUrl;
this.dbUserName = dbUserName;
this.dbPassword = dbPassword;
LOGGER.finer("with String[] trace");
return filterAuthorized(new ArrayList<String>(Arrays.asList(pubdidArr)), dbConnUrl);
}
private String[] filterAuthorized(ArrayList<String> pubdidList, String dbConnUrl)
{
LOGGER.fine("with List <String> trace");
switch(access)
{
case PUBLIC_ONLY :
filterNotPublic(pubdidList, dbConnUrl);
break;
case PUBLIC_AND_AUTHORIZED_PRIVATE :
filterNotAuthorized(pubdidList, dbConnUrl);
break;
default :
assert false : "Unrecoginzed access : " + access;
}
return pubdidList.toArray(new String[0]);
}
private void filterNotPublic(ArrayList<String> pubdids, String dbConnUrl)
{
LOGGER.fine("trace");
assert pubdids != null;
LOGGER.finer("PublisherDID list original : " + String.join(" ", pubdids));
List<AuthPolicyDb.PubdidGroups> privateUniqPubdids = db_queryPrivateUniqPubdidGroups(dbConnUrl, pubdids);
List<String> notAuthorizedUniqPubdids = pubdidsNotPublic(privateUniqPubdids, userGroups);
LOGGER.finest("AuthZ removes: " + String.join(" ", notAuthorizedUniqPubdids));
removeNotAuthorized(pubdids, notAuthorizedUniqPubdids);
LOGGER.finest("PublisherDID list filtered : " + (pubdids.isEmpty() ? "" : String.join(" ", pubdids)));
}
private List<String> pubdidsNotPublic(List<AuthPolicyDb.PubdidGroups> pubdidList, String[] userGroups)
{
LOGGER.fine("trace");
LOGGER.finer("userGroups: " + String.join(" ",userGroups));
List<String> pubdidsNotAuthorizedList = new LinkedList<String>();
ListIterator<AuthPolicyDb.PubdidGroups> it = pubdidList.listIterator();
while (it.hasNext())
{
AuthPolicyDb.PubdidGroups pubdidGroups = it.next();
LOGGER.finest(pubdidGroups.pubdid + " : " + String.join(" ",pubdidGroups.groups));
if( true )// isIntersectionEmpty(pubdidGroups.groups, userGroups) )
{
pubdidsNotAuthorizedList.add(pubdidGroups.pubdid);
}
}
return pubdidsNotAuthorizedList;
}
private void filterNotAuthorized(ArrayList<String> pubdids, String dbConnUrl)
{
LOGGER.fine("trace");
assert pubdids != null;
LOGGER.finer("PublisherDID list original : " + String.join(" ", pubdids));
List<AuthPolicyDb.PubdidGroups> privateUniqPubdids = db_queryPrivateUniqPubdidGroups(dbConnUrl, pubdids);
List<String> notAuthorizedUniqPubdids = pubdidsNotAuthorized(privateUniqPubdids, userGroups);
LOGGER.finest("AuthZ removes: " + String.join(" ", notAuthorizedUniqPubdids));
removeNotAuthorized(pubdids, notAuthorizedUniqPubdids);
LOGGER.finest("PublisherDID list filtered : " + (pubdids.isEmpty() ? "" : String.join(" ", pubdids)));
}
private void removeNotAuthorized(ArrayList<String> pubdids, List<String> notAuthorizedUniqPubdids)
{
ListIterator<String> itr = pubdids.listIterator();
while (itr.hasNext())
{
String pubdid = itr.next();
for(String notAuthPubdid : notAuthorizedUniqPubdids)
{
if (pubdid.equals(notAuthPubdid)) itr.remove();
}
}
return;
}
private List<AuthPolicyDb.PubdidGroups> db_queryPrivateUniqPubdidGroups(String dbConnUrl, List<String> pubdids)
{
AuthPolicyDb adb;
synchronized(AuthPolicyDb.class)
{
//AuthPolicyDb.dbConnUrl = this.dbConnUrl;
AuthPolicyDb.dbUserName = this.dbUserName;
AuthPolicyDb.dbPassword = this.dbPassword;
adb = new AuthPolicyDb();
}
Set<String> uniqPubdids = new HashSet<String>(pubdids);
if(uniqPubdids.isEmpty())
{
List<AuthPolicyDb.PubdidGroups> privatePubdidGroups = Collections.emptyList();
return privatePubdidGroups;
}
else
{
// FIXME handle DB-exceptions
List<AuthPolicyDb.PubdidGroups> privatePubdidGroups = adb.queryGroupsPrivateOnly(uniqPubdids);
return privatePubdidGroups;
}
}
private List<String> pubdidsNotAuthorized(List<AuthPolicyDb.PubdidGroups> pubdidList, String[] userGroups)
{
LOGGER.fine("trace");
//LOGGER.finer("userGroups: " + String.join(" ",userGroups));
List<String> pubdidsNotAuthorizedList = new LinkedList<String>();
ListIterator<AuthPolicyDb.PubdidGroups> it = pubdidList.listIterator();
while (it.hasNext())
{
AuthPolicyDb.PubdidGroups pubdidGroups = it.next();
LOGGER.finest(pubdidGroups.pubdid + " : " + String.join(" ",pubdidGroups.groups));
if( isIntersectionEmpty(pubdidGroups.groups, userGroups) )
{
pubdidsNotAuthorizedList.add(pubdidGroups.pubdid);
}
}
return pubdidsNotAuthorizedList;
}
private boolean isIntersectionEmpty(String[] stringsA, String[] stringsB)
{
for(String strA : stringsA)
for(String strB : stringsB)
{
if(strA.equals(strB))
{
return false;
}
}
return true;
}
}