There are two possible changes that I can suggest ... and one comment.
First , put your primitive checks in the chain as far as possible. Throw exceptions to report authorization errors.
void readBook (Book &book) { // readbook doesn't need to perform any checks of it own. // the more primitive actions will scream and yell if the user // isn't allowed to perform sub-action X. openBook(book); BookData d = getBookData(book); // etc. } void openBook (Book &book) { if (!checkSecurity (book, OPENBOOK)) throw new SecurityException("User X is not allowed to open this book!"); // etc. } BookData getBookData (Book &book) { if (!checkSecurity (book, SEEBOOK)) throw new SecurityException("User X is not allowed to read this book data!"); // etc. }
Second , compare your security actions with actual actions. You can even do this in the data if you want. For instance...
class Security { // this check get tricky. // if an "real action" isn't listed anywhere, does the user have implicit permission? // (i'm assuming not, for this example.) public static Check(String realAction, Boolean requireAll = true) { Int32 required = 0; Int32 userHas = 0; foreach (KeyValuePair<String, List<String>> pair in Actions) { if (pair.Value.Contains(realAction)) { required++; if (Security.CurrentUser.Actions.Contains(pair.Key)) { userHas++; } } } if (requireAll) { return userHas > 0 && userHas == required; } else { return userHas > 0; } } // hardcoded here, but easily populated from a database or config file public static Dictionary<String, List<String>> Actions { {"OpenBook", new List<String>() { "readBook", "writeBook" }}, {"SeeBook", new List<String>() { "readBook", "writeBook" }} } } void readBook(Book &book) { if (!Security.Check("readBook")) return false; // etc. }
This Check() method uses the requireAll parameter, but the mappings themselves can just as easily be updated to "insist" or "prefer" to be present for their alleged "real actions".
And my comment . Do not reset your safety. Some safety rules imply other rules that may be meaningless on their own. For example, READBOOK and WRITEBOOK both imply OPENBOOK , and OPENBOOK seems to be pointless. Although OPENBOOK or WRITEBOOK might seem silly to the user without such things as SEEBOOKCOVER and SEEBOOKINSEARCHRESULTS or something else, I would suggest that the only relevant permission when reading a book is READBOOK .
source share