package org.triiskelion.tinyspring.security; import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; /** * Set of privileges defining the capabilities of one role or one user. * * @author Sebastian */ public class Privileges implements Cloneable { private static final Logger log = LoggerFactory.getLogger(Privileges.class); String name = ""; String description = ""; int value = -1; Map<String, Privileges> items = new HashMap<>(); Map<String, Privileges> subsets = new HashMap<>(); public Privileges() { } public Privileges(String name, String description) { this.name = name; this.description = description; } public Privileges(String name, String description, int value) { this.name = name; this.description = description; this.value = value; } public Map<String, Privileges> getItems() { return items; } public void setItems(Map<String, Privileges> items) { this.items = items; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Map<String, Privileges> getSubsets() { return subsets; } public void setSubsets(Map<String, Privileges> subsets) { this.subsets = subsets; } public String toString() { return JSONObject.toJSONString(this, true); } public Privileges clone() { Privileges result = new Privileges(); result.name = this.name; result.description = this.description; result.value = this.value; for(String key : this.getItems().keySet()) { result.getItems().put(key, this.getItems().get(key).clone()); } for(String key : this.getSubsets().keySet()) { result.getItems().put(key, this.getSubsets().get(key).clone()); } return result; } /** * Returns a copy of this instance merged with another one.<p> * This instance is immutable and unaffected by this method call. * * @param privilege * another privilege instance * * @return a copy of this instance merged with another */ public Privileges merge(Privileges privilege) { if(privilege == null) { throw new IllegalArgumentException(); } Privileges result = this.clone(); if(result == null) { throw new RuntimeException(); } if(result.getItems() != null && privilege.getItems() != null) { for(String key : privilege.getItems().keySet()) { if(result.getItems().get(key) != null) { result.getItems().get(key).setValue( Math.max(result.getItems().get(key).getValue(), privilege.getItems().get(key).getValue()) ); } else { result.getItems().put(key, privilege.getItems().get(key).clone()); } } } if(result.getSubsets() != null && privilege.getSubsets() != null) { for(String key : privilege.getSubsets().keySet()) { if(result.getSubsets().get(key) == null) { result.getSubsets().put(key, new Privileges()); } result.getSubsets().put(key, result.getSubsets().get(key).merge(privilege.getSubsets().get(key))); } } return result; } public static Privileges parse(@Nullable String... privilegeSet) { if(privilegeSet == null || privilegeSet.length == 0) { return null; } ArrayList<Privileges> list = new ArrayList<>(); for(String json : privilegeSet) { Privileges set = JSONObject.parseObject(json, Privileges.class); list.add(set); } //merge them into one Privileges finalResult = new Privileges(); for(Privileges set : list) { finalResult.merge(set); } return finalResult; } /** * Retrieve a privilege from an privilege set. * * @param key * the key of the privilege * * @return value of the privilege or -1 if not found */ public int getValue(@NotNull String key) { if(StringUtils.isBlank(key)) { throw new IllegalArgumentException("privilege key is blank."); } String[] keys = StringUtils.split(key, "."); if(keys == null) { throw new IllegalArgumentException("Could not split key: " + key); } return getValue(this, keys, 0); } protected static int getValue(Privileges set, @NotNull String[] key, int index) { if(index == key.length - 1) { // position Privileges item = set.getItems().get(key[index]); if(item == null) { log.warn("privilege {} not found", StringUtils.join(key, ".")); return -1; } else { return item.getValue(); } } else if(index < key.length - 1) { Privileges subset = set.getSubsets().get(key[index]); return subset == null ? -1 : getValue(set, key, index + 1); } throw new RuntimeException("Should never getValue here."); } }