package org.intellimate.izou.security; import org.intellimate.izou.addon.AddOnModel; import org.intellimate.izou.main.Main; import org.intellimate.izou.security.exceptions.IzouPermissionException; import org.intellimate.izou.util.IdentifiableSet; import org.intellimate.izou.util.IzouModule; import ro.fortsoft.pf4j.PluginDescriptor; import ro.fortsoft.pf4j.PluginWrapper; import java.security.Permission; import java.util.function.Function; import java.util.function.Supplier; /** * A PermissionModule defines basic permissions in Izou. A permission in Izou is defined as service that is generally * allowed, yet the addOn has to be registered in order to use the service. * <p> * For example, socket connections are generally allowed for Izou addOns yet in order to use them their usage has * to be declared in the addon_config.properties file of the addOn. * </p> * <p> * Thus {@code PermissionModule} implements a registration system for services like socket connection. * </p> */ public abstract class PermissionModule extends IzouModule { private final IdentifiableSet<AddOnModel> registeredAddOns; private final SecurityManager securityManager; /** * Creates a new PermissionModule * @param main an instance of main * @param securityManager an instance of securityManager */ PermissionModule(Main main, SecurityManager securityManager) { super(main); registeredAddOns = new IdentifiableSet<>(); this.securityManager = securityManager; } /** * returns an instance of SecurityManager * @return the SecurityManager */ public SecurityManager getSecurityManager() { return securityManager; } /** * Throws an exception with the argument of {@code argument} * @param argument what the exception is about (Access denied to (argument goes here)) */ SecurityException getException(String argument) { return securityManager.getException(argument); } /** * returns true if able to check permissions * @param permission the permission to check * @return true if able to, false if not */ public abstract boolean canCheckPermission(Permission permission); /** * Adds an addOn to the registered addOns list for this PermissionModule * * @param addon the Identifiable to add */ public void registerAddOn(AddOnModel addon) { registeredAddOns.add(addon); } /** * Checks if an addOn is registered with this PermissionModule * * @param addon the identifiable to check * @return true if the addOn is registered, else false */ public boolean isRegistered(AddOnModel addon) { return registeredAddOns.contains(addon); } /** * Checks if the given addOn is allowed to access the requested service. * * @param addon the identifiable to check * @param permission the Permission to check * @throws SecurityException thrown if the addOn is not allowed to access its requested service */ public abstract void checkPermission(Permission permission, AddOnModel addon) throws SecurityException; /** * registers the addon if checkPermission returns true, else throws the exception provided by the exceptionSupplier. * If the Addon was not added through PF4J it gets ignored * @param addOn the addon to check * @param checkPermission returns true if eligible for registering */ protected <X extends IzouPermissionException> void registerOrThrow(AddOnModel addOn, Supplier<X> exceptionSupplier, Function<PluginDescriptor, Boolean> checkPermission) { getMain().getAddOnManager().getPluginWrapper(addOn) .map(PluginWrapper::getDescriptor) .map(checkPermission) .ifPresent(allowedToRun -> { if (allowedToRun) { registerAddOn(addOn); } else { throw exceptionSupplier.get(); } }); } }