Solution for lots of flags
Hi. When I need to have rights management in my programs, I usually make an enum "Rights" as [Flags] type long and do like
Invalid = -1,
None = 0,
AddGame = 1,
DelGame = 2,
LaunchGame = 4,
EditGame = 8
..etc
I like because it's simple bitwise and I made an extension method so I can just do like
function DeleteGame(Game game) {
if (!ActiveUser?.Rights.HasPermission(Rights.DeleteGame) ?? false) return;
However... I'm doing a big complex app and it's gonna have more rights than I have bits in a long. What is a good way to handle it at that point? I figured I could do enums like
Rights_Context1
Rights_Context2
..etc
then I was trying to figure out how to store them in the user. I figured maybe
public List<Enum> Rights
then load them all into there, but then how do I check them? Loop and check what type each entry is then compare? That seems awkward.
Is there any easy solution for having large amounts of flags in an enum? I assume I need a bitwise enum because I want to store the data in the db, and a bigint seemed the easiest way. I suppose I could do a permissions related table then make single entries per flag but that seems very inefficient.
7 Replies
if you have a large amount of flags you shouldn't use an enum, because you're fundamentally limited by the largest integer type you can use as the enum type
i would use a permissions table, databases are designed for that type of layout
it might seem more inefficient but it's also less likely to break by accident and it would only be a problem if you actually run into performance issues because of it
So like when I do a permission check, just have a method that does like
SELECT index FROM permissions WHERE uid = ?uid AND permcode = ?perm
Then pass the user Guid and maybe a string like "game.delete" then if a row is returned, I know they're authorized else deny?
Roundtripping to MySQL that much won't be an issue? Well, it's not like I'm making some high use app anyway lol so I doubt it'd be an issue. Just curious.
Hmm I could keep a cache in the perm manager and when an admin changes ppls perms, flush cache and/or flush it every X minutes that may reduce load.
do you necessarily need to or can you cache permissions for some amount of time?
you can just load them into a hashset and refresh it if the permissions are changed
Thanks, appreciate the advice!
I have a followup question. I'm working on implementing this. I have a static Perm class now, with a private Dictionary<Guid, HashSet<string>> Permissions. I have an Init method that populates the dict with the user's ID's then all the nodes to which they have permission. Then I have:
But I'd like to support inheritance. Like If I have nodes like:
If I'm checking for Game.View, then if they have edit, delete or launch it stands to reason that view is a given. What would be a good way to handle that?
GetInheritanceSet returns a HashSet with all the nodes that would grant the key node, like
So if I do Has("Game.View") and the user doesn't explicitly have that but they do have Game.Launch, it would return true. Does that look workable?
yes
there's no reason for it to be a hash set if it's static data though
also, what is that ToLower().Trim() doing there?
I liked the bitsets. I'd prefer integer ids instead of strings at least
if you know the max amount of roles you'll have, you can do a struct with a bunch of integer fields to accommodate the max
for the bitset
Ahh. What would I use if not the hashset for the static data then? The tolower trim was to normalize the input, but that's gone now as I switched to using an enum for the permission nodes rather than typing them as strings. Roles are variable, users can add them.
Thanks!
an array