DS-2347 ShibAuthentication fix to work with metadata for all - clean

This commit is contained in:
philip Vissenaekens
2014-12-08 11:13:38 +01:00
parent 58f7734400
commit 191d9b68bb

View File

@@ -7,13 +7,10 @@
*/
package org.dspace.authenticate;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.http.HttpServletRequest;
@@ -34,6 +31,9 @@ import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema;
import org.dspace.content.NonUniqueMetadataException;
import org.dspace.core.Context;
import org.dspace.core.ConfigurationManager;
import org.dspace.authenticate.AuthenticationManager;
@@ -180,7 +180,7 @@ public class ShibAuthentication implements AuthenticationMethod
}
// Initialize the additional EPerson metadata.
initialize();
initialize(context);
// Log all headers received if debugging is turned on. This is enormously
// helpful when debugging shibboleth related problems.
@@ -894,8 +894,9 @@ public class ShibAuthentication implements AuthenticationMethod
* the field will be automatically created.
*
* It is safe to call this methods multiple times.
* @param context
*/
private synchronized static void initialize() throws SQLException {
private synchronized static void initialize(Context context) throws SQLException {
if (metadataHeaderMap != null)
return;
@@ -931,10 +932,10 @@ public class ShibAuthentication implements AuthenticationMethod
String header = metadataParts[0].trim();
String name = metadataParts[1].trim().toLowerCase();
boolean valid = checkIfEpersonMetadataFieldExists(name);
boolean valid = checkIfEpersonMetadataFieldExists(name,context);
if ( ! valid && autoCreate) {
valid = autoCreateEpersonMetadataField(name);
valid = autoCreateEpersonMetadataField(name,context);
}
if (valid) {
@@ -953,18 +954,13 @@ public class ShibAuthentication implements AuthenticationMethod
}
/**
* Check the EPerson table definition to see if the metadata field name is supported. It
* checks for three things 1) that the field exists and 2) that the field is of the correct
* type, varchar, and 3) that the field's size is sufficient.
* Check if a MetadataField for an eperson is available.
*
* If either of these checks fail then false is returned.
*
* If all these checks pass then true is returned, otherwise false.
*
* @param metadataName The name of the metadata field.
* @param context
* @return True if a valid metadata field, otherwise false.
*/
private static synchronized boolean checkIfEpersonMetadataFieldExists(String metadataName) throws SQLException {
private static synchronized boolean checkIfEpersonMetadataFieldExists(String metadataName, Context context) throws SQLException {
if (metadataName == null)
return false;
@@ -973,47 +969,23 @@ public class ShibAuthentication implements AuthenticationMethod
// The phone is a predefined field
return true;
// Get a list of all the columns on the eperson table.
Connection dbConnection = null;
try {
dbConnection = DatabaseManager.getConnection();
DatabaseMetaData dbMetadata = dbConnection.getMetaData();
String dbCatalog = dbConnection.getCatalog();
ResultSet rs = dbMetadata.getColumns(dbCatalog,null,"eperson","%");
MetadataSchema schemaObj = MetadataSchema.find(context, "eperson");
// Loop through all the columns looking for our metadata field and check
// it's definition.
boolean foundColumn = false;
boolean columnValid = false;
while (rs.next()) {
String columnName = rs.getString("COLUMN_NAME");
String columnType = rs.getString("TYPE_NAME");
int size = rs.getInt("COLUMN_SIZE");
if (schemaObj == null)
{
log.error("Schema eperson is not registered and does not exist.");
} else
{
MetadataField eperson = MetadataField.findByElement(context, schemaObj.getSchemaID(), metadataName, null);
if (metadataName.equalsIgnoreCase(columnName)) {
foundColumn = true;
if ("varchar".equals(columnType) && size >= METADATA_MAX_SIZE)
columnValid = true;
break; // skip out on loop after we found our column.
if ( eperson!=null) {
return true;
}
else {
log.error("Unable to find eperson named: '" + metadataName + "'");
}
}
} // while rs.next()
rs.close();
if ( foundColumn && columnValid)
// The finally statement below will close the connection.
return true;
else if (!foundColumn)
log.error("Unable to find eperson column for additional metadata named: '"+metadataName+"'");
else if (!columnValid)
log.error("The eperson column for additional metadata, '"+metadataName+"', is not defined as a varchar with at least a length of "+METADATA_MAX_SIZE);
} finally {
if (dbConnection != null)
dbConnection.close();
}
return false;
}
@@ -1021,13 +993,12 @@ public class ShibAuthentication implements AuthenticationMethod
private static final String COLUMN_NAME_REGEX = "^[_A-Za-z0-9]+$";
/**
* Automattically create a new column in the EPerson table to support the additional
* metadata field. All additional fields are created with type varchar( METADATA_MAX_SIZE )
* Automattically create a new metadataField for an eperson
*
* @param metadataName The name of the new metadata field.
* @return True if successful, otherwise false.
*/
private static synchronized boolean autoCreateEpersonMetadataField(String metadataName) throws SQLException {
private static synchronized boolean autoCreateEpersonMetadataField(String metadataName, Context context) throws SQLException {
if (metadataName == null)
return false;
@@ -1039,29 +1010,33 @@ public class ShibAuthentication implements AuthenticationMethod
if ( ! metadataName.matches(COLUMN_NAME_REGEX))
return false;
// Create a new column for the metadata field. Note the metadataName variable is embedded because we can't use
// paramaterization for column names. However the string comes from the dspace.cfg and at the top of this method
// we run a regex on it to validate it.
String sql = "ALTER TABLE eperson ADD COLUMN "+metadataName+" varchar("+METADATA_MAX_SIZE+")";
Connection dbConnection = null;
MetadataSchema schemaObj = MetadataSchema.find(context, "eperson");
if (schemaObj == null)
{
log.error("Schema eperson is not registered and does not exist.");
} else {
MetadataField metadataField = new MetadataField(schemaObj, metadataName, null, null);
try {
dbConnection = DatabaseManager.getConnection();
Statement alterStatement = dbConnection.createStatement();
alterStatement.execute(sql);
alterStatement.close();
dbConnection.commit();
metadataField.create(context);
} catch (IOException e) {
log.error("Unable to auto-create the eperson MetadataField with MetadataName " + metadataName ,e);
return false;
} catch (AuthorizeException e) {
log.error("Unauthorized to auto-create the eperson MetadataField with MetadataName " + metadataName + " MetadataField", e);
return false;
} catch (NonUniqueMetadataException e) {
log.error("The eperson MetadataField with MetadataName " + metadataName +" already exists",e);
return false;
}
log.info("Auto created the eperson column for additional metadata: '"+metadataName+"'");
log.info("Auto created the eperson metadataField: '" + metadataName + "'");
return true;
} catch (SQLException sqle) {
log.error("Unable to auto-create the eperson column for additional metadata '"+metadataName+"', because of error: ",sqle);
}
return false;
} finally {
if (dbConnection != null)
dbConnection.close();
}
}