/* * 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.permissions; import org.obiba.magma.Datasource; import org.obiba.magma.ValueTable; import org.obiba.magma.Variable; import org.obiba.magma.security.Authorizer; import com.google.common.base.Predicate; public class Permissions { public static final String WILDCARD = "*"; private Permissions() {} public static final class Actions { public static final String READ = "GET"; public static final String WRITE = "POST"; public static final String DELETE = "DELETE"; private Actions() {} } @SuppressWarnings({ "ParameterHidesMemberVariable", "UnusedDeclaration" }) public static class Builder<T extends Builder<?>> { protected String domain; String action; protected StringBuilder path = new StringBuilder(); public Builder() { } private Builder(Builder<?> builder) { domain = builder.domain; action = builder.action; path = new StringBuilder(builder.path); } public T domain(String domain) { this.domain = domain; return asT(); } public T anyDomain() { domain = WILDCARD; return asT(); } public T action(String action) { this.action = action; return asT(); } public T anyAction() { action = WILDCARD; return asT(); } public T read() { action = Actions.READ; return asT(); } public T delete() { action = Actions.DELETE; return asT(); } public T instance(String instance) { path.append('/').append(instance); return asT(); } public T instances(String... instances) { for(String i : instances) { instance(i); } return asT(); } public String build() { return appendNonNull(domain, path.toString(), action); } @SuppressWarnings("unchecked") private T asT() { return (T) this; } /** * Appends <code>":" + segment</code> to <code>permission</code> when <code>segment</code> is non-null. */ private String appendNonNull(String permission, String segment) { return permission + (segment != null ? ":" + segment : ""); } private String appendNonNull(String permission, String... segments) { String newPermission = permission; for(String segment : segments) { newPermission = appendNonNull(newPermission, segment); } return newPermission; } } @SuppressWarnings("StaticMethodOnlyUsedInOneClass") public static class DatasourcePermissionBuilder extends Builder<DatasourcePermissionBuilder> { private static final String DOMAIN = "magma"; private DatasourcePermissionBuilder(DatasourcePermissionBuilder other) { super(other); } private DatasourcePermissionBuilder() { } public static DatasourcePermissionBuilder forDatasource(String name) { DatasourcePermissionBuilder db = new DatasourcePermissionBuilder(); db.domain(DOMAIN).instance("datasource").instance(name); return db; } public static DatasourcePermissionBuilder forDatasource(Datasource datasource) { return forDatasource(datasource.getName()); } public static DatasourcePermissionBuilder forDatasource() { DatasourcePermissionBuilder db = new DatasourcePermissionBuilder(); db.domain(DOMAIN); return db; } protected DatasourcePermissionBuilder newCopy() { return new DatasourcePermissionBuilder(this); } public ValueTablePermissionBuilder tables() { // TODO: should we add "/tables" to the path? return new ValueTablePermissionBuilder(this)/* .instance("tables") */; } public ValueTablePermissionBuilder table(ValueTable table) { return new ValueTablePermissionBuilder(this).instance("table").instance(table.getName()); } public ValueTablePermissionBuilder table(String name) { return new ValueTablePermissionBuilder(this).instance("table").instance(name); } public Predicate<Datasource> asPredicate(final Authorizer authorizer) { return new Predicate<Datasource>() { @Override public boolean apply(Datasource input) { return authorizer.isPermitted(newCopy().instance("datasource").instance(input.getName()).build()); } }; } } @SuppressWarnings("StaticMethodOnlyUsedInOneClass") public static class ValueTablePermissionBuilder extends Builder<ValueTablePermissionBuilder> { ValueTablePermissionBuilder(DatasourcePermissionBuilder builder) { super(builder); } private ValueTablePermissionBuilder(ValueTablePermissionBuilder builder) { super(builder); } protected ValueTablePermissionBuilder newCopy() { return new ValueTablePermissionBuilder(this); } public static ValueTablePermissionBuilder forValueTable(ValueTable table) { return DatasourcePermissionBuilder.forDatasource(table.getDatasource()).table(table); } public VariablePermissionBuilder variable(Variable variable) { return new VariablePermissionBuilder(this).instance("variable").instance(variable.getName()); } public VariablePermissionBuilder variable(String variable) { return new VariablePermissionBuilder(this).instance("variable").instance(variable); } public Predicate<ValueTable> asPredicate(final Authorizer authorizer) { return new Predicate<ValueTable>() { @Override public boolean apply(ValueTable input) { return authorizer.isPermitted(newCopy().instance("table").instance(input.getName()).build()); } }; } } @SuppressWarnings("UnusedDeclaration") public static class VariablePermissionBuilder extends Builder<VariablePermissionBuilder> { public VariablePermissionBuilder(ValueTablePermissionBuilder builder) { super(builder); } private VariablePermissionBuilder(VariablePermissionBuilder builder) { super(builder); } protected VariablePermissionBuilder newCopy() { return new VariablePermissionBuilder(this); } public Predicate<Variable> asPredicate(final Authorizer authorizer) { return new Predicate<Variable>() { @Override public boolean apply(Variable input) { return authorizer.isPermitted(newCopy().instance("variable").instance(input.getName()).build()); } }; } } }