/*
* Copyright (c) 2017 OBiBa. All rights reserved.
*
* This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.obiba.magma.security;
import java.util.ArrayList;
import java.util.concurrent.Callable;
import org.obiba.magma.Datasource;
import org.obiba.magma.MagmaEngine;
import org.obiba.magma.NoSuchDatasourceException;
import org.obiba.magma.NoSuchValueTableException;
import org.obiba.magma.ValueTable;
import org.obiba.magma.support.AbstractDatasourceWrapper;
import org.obiba.magma.support.StaticDatasource;
import org.obiba.magma.support.StaticValueTable;
import org.obiba.magma.support.ValueTableReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An implementation of {@link ValueTableReference} that uses super user privileges to access the referenced table.
* <p/>
* Note that this implementation will also remove the {@link SecuredValueTable} decorator such that the returned table
* is no longer secured.
*/
public class SudoValueTableReference extends ValueTableReference {
private static final Logger log = LoggerFactory.getLogger(SudoValueTableReference.class);
private final Authorizer authz;
private Datasource wrappedDatasource;
public SudoValueTableReference(Authorizer authz, String reference) {
super(reference);
this.authz = authz;
}
@Override
public ValueTable getWrappedValueTable() {
return sudo();
}
/**
* Escalates user privileges to obtain the referenced valueTable. If successful, the result is an unsecured
* ValueTable.
*
* @return
*/
protected ValueTable sudo() {
try {
if(wrappedDatasource == null) {
wrappedDatasource = authz.silentSudo(new DatasourceCallable());
}
return wrappedDatasource.getValueTable(getResolver().getTableName());
} catch(NoSuchValueTableException e) {
log.warn("No such value table in '{}': {}. {}", getReference(), e.getMessage());
return getDummyValueTable(wrappedDatasource);
} catch (NoSuchDatasourceException e) {
log.warn("No such datasource for value table: {}. {}", getReference(), e.getMessage());
return getDummyValueTable(new StaticDatasource(getResolver().getDatasourceName()));
} catch(RuntimeException e) {
log.warn("Unexpected error in value table '{}' lookup: {}", getReference(), e.getMessage());
log.debug("Unexpected error", e);
return getDummyValueTable(new StaticDatasource(getResolver().getDatasourceName()));
}
}
// OPAL-1821
private ValueTable getDummyValueTable(Datasource ds) {
return new StaticValueTable(ds, getResolver().getTableName(), new ArrayList<String>(), "?");
}
private class DatasourceCallable implements Callable<Datasource> {
@Override
public Datasource call() throws Exception {
return unwrap(MagmaEngine.get().getDatasource(getResolver().getDatasourceName()));
}
private Datasource unwrap(Datasource ds) {
return ds instanceof SecuredDatasource ? ((AbstractDatasourceWrapper) ds).getWrappedDatasource() : ds;
}
}
}