001package org.intellimate.izou.security; 002 003import org.intellimate.izou.addon.AddOnModel; 004import org.intellimate.izou.main.Main; 005import org.intellimate.izou.security.exceptions.IzouPermissionException; 006import org.intellimate.izou.util.IdentifiableSet; 007import org.intellimate.izou.util.IzouModule; 008import ro.fortsoft.pf4j.PluginDescriptor; 009import ro.fortsoft.pf4j.PluginWrapper; 010 011import java.security.Permission; 012import java.util.function.Function; 013import java.util.function.Supplier; 014 015/** 016 * A PermissionModule defines basic permissions in Izou. A permission in Izou is defined as service that is generally 017 * allowed, yet the addOn has to be registered in order to use the service. 018 * <p> 019 * For example, socket connections are generally allowed for Izou addOns yet in order to use them their usage has 020 * to be declared in the addon_config.properties file of the addOn. 021 * </p> 022 * <p> 023 * Thus {@code PermissionModule} implements a registration system for services like socket connection. 024 * </p> 025 */ 026public abstract class PermissionModule extends IzouModule { 027 private final IdentifiableSet<AddOnModel> registeredAddOns; 028 private final SecurityManager securityManager; 029 030 /** 031 * Creates a new PermissionModule 032 * @param main an instance of main 033 * @param securityManager an instance of securityManager 034 */ 035 PermissionModule(Main main, SecurityManager securityManager) { 036 super(main); 037 registeredAddOns = new IdentifiableSet<>(); 038 this.securityManager = securityManager; 039 } 040 041 /** 042 * returns an instance of SecurityManager 043 * @return the SecurityManager 044 */ 045 public SecurityManager getSecurityManager() { 046 return securityManager; 047 } 048 049 /** 050 * Throws an exception with the argument of {@code argument} 051 * @param argument what the exception is about (Access denied to (argument goes here)) 052 */ 053 SecurityException getException(String argument) { 054 return securityManager.getException(argument); 055 } 056 057 /** 058 * returns true if able to check permissions 059 * @param permission the permission to check 060 * @return true if able to, false if not 061 */ 062 public abstract boolean canCheckPermission(Permission permission); 063 064 /** 065 * Adds an addOn to the registered addOns list for this PermissionModule 066 * 067 * @param addon the Identifiable to add 068 */ 069 public void registerAddOn(AddOnModel addon) { 070 registeredAddOns.add(addon); 071 } 072 073 /** 074 * Checks if an addOn is registered with this PermissionModule 075 * 076 * @param addon the identifiable to check 077 * @return true if the addOn is registered, else false 078 */ 079 public boolean isRegistered(AddOnModel addon) { 080 return registeredAddOns.contains(addon); 081 } 082 083 /** 084 * Checks if the given addOn is allowed to access the requested service. 085 * 086 * @param addon the identifiable to check 087 * @param permission the Permission to check 088 * @throws SecurityException thrown if the addOn is not allowed to access its requested service 089 */ 090 public abstract void checkPermission(Permission permission, AddOnModel addon) throws SecurityException; 091 092 /** 093 * registers the addon if checkPermission returns true, else throws the exception provided by the exceptionSupplier. 094 * If the Addon was not added through PF4J it gets ignored 095 * @param addOn the addon to check 096 * @param checkPermission returns true if eligible for registering 097 */ 098 protected <X extends IzouPermissionException> void registerOrThrow(AddOnModel addOn, Supplier<X> exceptionSupplier, 099 Function<PluginDescriptor, Boolean> checkPermission) { 100 getMain().getAddOnManager().getPluginWrapper(addOn) 101 .map(PluginWrapper::getDescriptor) 102 .map(checkPermission) 103 .ifPresent(allowedToRun -> { 104 if (allowedToRun) { 105 registerAddOn(addOn); 106 } else { 107 throw exceptionSupplier.get(); 108 } 109 }); 110 } 111}