/*
* Eduardo, an IRC bot framework
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) Eduardo team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.eduardo.service.auth.policy;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import java.util.function.Predicate;
import static com.google.common.base.Preconditions.checkNotNull;
public class MultiMapPolicy<T> implements Policy<T> {
private final Multimap<String, Predicate<T>> grant = HashMultimap.create();
private final Multimap<String, Predicate<T>> deny = HashMultimap.create();
@Override
public void grant(String permission, Predicate<T> predicate) {
checkNotNull(predicate);
grant.put(permission.toLowerCase(), predicate);
}
@Override
public void deny(String permission, Predicate<T> predicate) {
checkNotNull(predicate);
deny.put(permission.toLowerCase(), predicate);
}
@Override
public boolean testPermission(String permission, T context) {
String current = permission.replaceAll("\\.+", ".");
int lastIndex = current.length();
Result result = Result.NONE;
Result wildcard = getResult("*", context);
switch (wildcard) {
case ALLOW: result = Result.ALLOW; break;
case DENY: return false;
default:
}
do {
current = current.substring(0, lastIndex);
Result r = getResult(current, context);
switch (r) {
case ALLOW: result = Result.ALLOW; break;
case DENY: return false;
default:
}
} while ((lastIndex = current.lastIndexOf('.')) != -1);
return result == Result.ALLOW;
}
public Result getResult(String permission, T context) {
for (Predicate<T> predicate : deny.get(permission)) {
if (predicate.test(context)) {
return Result.DENY;
}
}
for (Predicate<T> predicate : grant.get(permission)) {
if (predicate.test(context)) {
return Result.ALLOW;
}
}
return Result.NONE;
}
public static enum Result {
ALLOW,
DENY,
NONE
}
}