I'm trying to create an authorization scheme for my ASP.NET MVC application where an Enum is used to set permissions. For example:
[Flags]
enum Permissions
{
ReadAppointments = 1,
WriteAppointments = 2 | ReadAppointments,
ReadPatients = 4,
WritePatients = 8 | ReadPatients,
ReadInvoices = 16,
WriteInvoices = 32 | ReadInvoices
...
}
But I don't really like that because it really doesn't make it clear that Write always includes Read.
I then realized that a requirement would be that a user might have NO access to, for example, Appointments.
Essentially, I'd want a "bitfield" with 3 states: none, readonly, full (read/write). I'd like to still use an enum bitfield since it's easy to store in a DB (as an int). Also it's very easy to see if a permission is set.
Does anyone have any idea how this could be easily accomplished using an Enum... or am I going in the completely wrong direction?
EDIT: I'm really trying to avoid storing permission definitions in the DB since I really want things to be changeable without having to modify much on the DB end. It'd be really nice to know how a large scale application would do this.
I would probably do this as separate fields for each area (Invoices. Patients, Appointments) using a single enum to cover each of them.
enum Permission { None, ReadOnly, ReadWrite };
To me, this is easier to understand and manage, and it doesn't combine a bunch of unrelated things (I should say "seemingly unrelated", since I don't know anything about your app).
wouldn't a value of 0 mean no permissions? ie:
0 is cannot modify appointments, patients, or invoices
1 is read appointments, but cannot modify others
2 is write appointments, but cannot modify others
3 is read/write appointments, but cannot modify others
4 is read patients, but cannot modify others.
so if you have...
51 that's:
read/write invoices and read/write appointments, but no access to patients...
Strictly speaking, you can't have a bitfield with anything other than two possible values any more than you can have a single (decimal) numeric digit with more than ten possible values. Base 2 means two values.
With that out of the way, don't store business-specific permissions as binary values; you will regret it later. Store them individually. Feel free to use a bitfield for defining the specifics of the permission (none/read/write/etc.), but not the nature of the permission itself.
Why is this Community Wiki?
I borrowed and modified this example from: C# vs Java Enum (for those new to C#)
Regardless I would not use an enum, I would use a class which would allow for much more flexibility. Something like this may help, just don't add patients and invoices as that varies orthogonally from the issue of read and write permissions.
There are many ways to do the bit manipulations and that should probably be done on a separate layer of code. If you need bit manipulations for serialization (to a file or database) then you should put that code there.
I don't use C# much so the syntax may be off, I do Java mostly. Anyway, the basic concept should be clear here:
public class Permissions
{
public static readonly Permissions NONE = new PERMISSIONS("NONE",false,false);
public static readonly Permissions READ = new PERMISSIONS("READ",true,false);
public static readonly Permissions FULL= new PERMISSIONS("FULL",true,true);
public static IEnumerable<Permissions> Values
{
get
{
yield return NONE;
yield return READ;
yield return FULL;
}
}
private readonly string name;
private readonly boolean read;
private readonly boolean write;
private readonly int bits;
Permissions(string name, boolean read,boolean write)
{
this.name = name;
this.read = read;
this.write= write;
this.bits = bits;
}
public string Name { get { return name; } }
// returns true if read permission is granted
public double isReadable { get { return read; } }
// returns true if write permission is granted
public double isWriteable { get { return write; } }
public override string ToString()
{
return name;
}
// returns bit field
public int bits { get { return write ? 1 : 0 | read ? 2 : 0; } }
}
Wrong direction. Your application will grow, then the bitfield will not be sufficient anymore and you are in for a lot of rework. Better get "proper" from the beginning.
Related
I have declared a basic struct like this
private struct ValLine {
public string val;
public ulong linenum;
}
and declared a Queue like this
Queue<ValLine> check = new Queue<ValLine>();
Then in a using StreamReader setup where I'm reading through the lines of an input file using ReadLine in a while loop, among other things, I'm doing this to populate the Queue:
check.Enqueue(new ValLine { val = line, linenum = linenum });
("line" is a string containing the text of each line, "linenum" is just a counter that is initialized at 0 and is incremented each time through the loop.)
The purpose of the "check" Queue is that if a particular line meets some criteria, then I store that line in "check" along with the line number that it occurs on in the input file.
After I've finished reading through the input file, I use "check" for various things, but then when I'm finished using it I clear it out in the obvious manner:
check.Clear();
(Alternatively, in my final loop through "check" I could just use .Dequeue(), instead of foreach'ing it.)
But then I got to thinking - wait a minute, what about all those "new ValLine" I generated when populating the Queue in the first place??? Have I created a memory leak? I've pretty new to C#, so it's not coming clear to me how to deal with this - or even if it should be dealt with (perhaps .Clear() or .Dequeue() deals with the now obsoleted structs automatically?). I've spent over an hour with our dear friend Google, and just not finding any specific discussion of this kind of example in regard to the clearing of a collection of structs.
So... In C# do we need to deal with wiping out the individual structs before clearing the queue (or as we are dequeueing), or not? And if so, then what is the proper way to do this?
(Just in case it's relevant, I'm using .NET 4.5 in Visual Studio 2013.)
UPDATE: This is for future reference (you know, like if this page comes up in a Google search) in regard to proper coding. To make the struct immutable as per recommendation, this is what I've ended up with:
private struct ValLine {
private readonly string _val;
private readonly ulong _linenum;
public string val { get { return _val; } }
public ulong linenum { get { return _linenum; } }
public ValLine(string x, ulong n) { _val = x; _linenum = n; }
}
Corresponding to that change, the queue population line is now this:
check.Enqueue(new ValLine(line,linenum));
Also, though not strictly necessary, I did get rid of my foreach on the queue (and the check.Clear();, and changed it to this
while (check.Count > 0) {
ValLine ll = check.Dequeue();
writer.WriteLine("[{0}] {1}", ll.linenum, ll.val);
}
so that the queue is emptied out as the information is output.
UPDATE 2: Okay, yes, I'm still a C# newbie (less than a year). I learn a lot from the Internet, but of course, I'm often looking at examples from more than a year ago. I have changed my struct so now it looks like this:
private struct ValLine {
public string val { get; private set; }
public ulong linenum { get; private set; }
public ValLine(string x, ulong n): this()
{ this.val = x; this.linenum = n; }
}
Interestingly enough, I had actually tried exactly this off the top of my head before coming up with what's in the first update (above), but got a compile error (because I did not have the : this() with the constructor). Upon further suggestion, I checked further and found a recent example showing that : this() for making it work like I tried before, plugged that in, and - Wa La! - clean compile. I like the cleaner look of the code. What the private variables are called is irrelevant to me.
No, you won't have created a memory leak. Calling Clear or Dequeue will clear the memory appropriately - for example, if you had a List<T> then a clear operation might use:
for (int i = 0; i < capacity; i++)
{
array[i] = default(T);
}
I don't know offhand whether Queue<T> is implemented with a circular buffer built on an array, or a linked list - but either way, you'll be fine.
Having said that, I would strongly recommend against using mutable structs as you're doing here, along with mutable fields. While it's not causing the particular problem you're envisaging, they can behave in confusing ways.
In my project i am using an Array of bool which defines the user's access rights.
For example
public bool[] Security {get; set;}
where
[0] = Admin
[1] = GrantWrites
[2] = GrantDeletes
[3] = User
It is working quite well.
I would set it to {F,T,F,T} or {0,1,0,1} and that particular user gets access as a User and it allows him to write.
I am trying to convert it to an enum but apparently i would need an array of it.
currently i have the following (not working)
public class UserCrops
{
public UserCrops(etc.., Enum[] _Security)
{
.
.
.
Security = _Security;
}
.
.
.
public Enum[] Security
{
Admin,
GrantWrites,
GrantDeletes,
User
}
}
I found some links like this but no help.
Thanks in advance
Edit: Both answers are very well explained but I am going with the non-Flag one just because it seems easier for me :)
Edit2: How can i create a new object (outside of class?)
I used to do
bool[] security = new bool[9];
for (int i = 0; i < 9; i++)
{
security[i] = chklstSecurity.Items[i].Selected;
}
userCropList.Add(new UserCrops(.., txtBiologicalAssessmentApprovalDate.Text, security));
But now?
Try with:
[Flags]
public enum Security
{
Admin = 1,
GrantWrites = 2,
GrantDeletes = 4,
User = 8
}
And you'll use it like this:
Security security = Security.GrantWrites | Security.GrantDeletes;
if ((security & Security.GrantWrites) == Security.GrantWrites)
{
}
Comparison can be simplified as pointed out by p.s.w.g. to increase its readability. Moreover I suggest to include a default value in the enum (for when variable is not initialized):
[Flags]
public enum Security
{
None = 0,
Admin = 1,
GrantWrites = 2,
GrantDeletes = 4,
User = 8
}
Finally note that you can provider shortcut for common combinations of flags:
[Flags]
public enum Security
{
// Other values
FullAccess = Admin | GrantWrites | GrantDeletes
}
More of that on MSDN. Please note this approach mimics attributes for file/directories in file system (and many other). IMO is much simpler to use than keep an array of enums as suggested in the other answer:
You do not have to search entire array to check if a permission is granted or not.
You do not have to check for a null value (enum can't be null, an array can be).
It uses less space (even if nowadays this is not so important).
It's naturally (more) safe so less checks are needed (for example to avoid duplicates inside array).
It can be easy stored (as text or integer without additional code).
But it has, compared to that, two main drawbacks:
Flags are finite (32 if you're using an Int32 for your enum or 64 for an Int64).
You can't easily switch to something else (if, for example, Security has to become a class you'll need to write much more code to mimic enums syntax and some assumption made by code when working with enums will be broken).
Remove the [] and use enum instead of Enum:
public enum Security
{
Admin,
GrantWrites,
GrantDeletes,
User
}
And you probably want to use Security[] as a method parameter:
public UserCrops(etc.., Security[] _Security)
Using flags (as Adriano suggests) is an excellent suggestion too, but it will require you to rethink how you're storing your permissions. Instead of storing an array of bool's, you'll represent the entire security set as a single value, with different bits representing each permission.
Read Enumeration Types (C# Programming Guide) under the section Enumeration Types as Bit Flags for more information.
I'm trying to figure out the best way to represent some data. It basically follows the form Manufacturer.Product.Attribute = Value. Something like:
Acme.*.MinimumPrice = 100
Acme.ProductA.MinimumPrice = 50
Acme.ProductB.MinimumPrice = 60
Acme.ProductC.DefaultColor = Blue
So the minimum price across all Acme products is 100 except in the case of product A and B. I want to store this data in C# and have some function where GetValue("Acme.ProductC.MinimumPrice") returns 100 but GetValue("Acme.ProductA.MinimumPrice") return 50.
I'm not sure how to best represent the data. Is there a clean way to code this in C#?
Edit: I may not have been clear. This is configuration data that needs to be stored in a text file then parsed and stored in memory in some way so that it can be retrieved like the examples I gave.
Write the text file exactly like this:
Acme.*.MinimumPrice = 100
Acme.ProductA.MinimumPrice = 50
Acme.ProductB.MinimumPrice = 60
Acme.ProductC.DefaultColor = Blue
Parse it into a path/value pair sequence:
foreach (var pair in File.ReadAllLines(configFileName)
.Select(l => l.Split('='))
.Select(a => new { Path = a[0], Value = a[1] }))
{
// do something with each pair.Path and pair.Value
}
Now, there two possible interpretations of what you want to do. The string Acme.*.MinimumPrice could mean that for any lookup where there is no specific override, such as Acme.Toadstool.MinimumPrice, we return 100 - even though there is nothing referring to Toadstool anywhere in the file. Or it could mean that it should only return 100 if there are other specific mentions of Toadstool in the file.
If it's the former, you could store the whole lot in a flat dictionary, and at look up time keep trying different variants of the key until you find something that matches.
If it's the latter, you need to build a data structure of all the names that actually occur in the path structure, to avoid returning values for ones that don't actually exist. This seems more reliable to me.
So going with the latter option, Acme.*.MinimumPrice is really saying "add this MinimumPrice value to any product that doesn't have its own specifically defined value". This means that you can basically process the pairs at parse time to eliminate all the asterisks, expanding it out into the equivalent of a completed version of the config file:
Acme.ProductA.MinimumPrice = 50
Acme.ProductB.MinimumPrice = 60
Acme.ProductC.DefaultColor = Blue
Acme.ProductC.MinimumPrice = 100
The nice thing about this is that you only need a flat dictionary as the final representation and you can just use TryGetValue or [] to look things up. The result may be a lot bigger, but it all depends how big your config file is.
You could store the information more minimally, but I'd go with something simple that works to start with, and give it a very simple API so that you can re-implement it later if it really turns out to be necessary. You may find (depending on the application) that making the look-up process more complicated is worse over all.
I'm not entirely sure what you're asking but it sounds like you're saying either.
I need a function that will return a fixed value, 100, for every product ID except for two cases: ProductA and ProductB
In that case you don't even need a data structure. A simple comparison function will do
int GetValue(string key) {
if ( key == "Acme.ProductA.MinimumPrice" ) { return 50; }
else if (key == "Acme.ProductB.MinimumPrice") { return 60; }
else { return 100; }
}
Or you could have been asking
I need a function that will return a value if already defined or 100 if it's not
In that case I would use a Dictionary<string,int>. For example
class DataBucket {
private Dictionary<string,int> _priceMap = new Dictionary<string,int>();
public DataBucket() {
_priceMap["Acme.ProductA.MinimumPrice"] = 50;
_priceMap["Acme.ProductB.MinimumPrice"] = 60;
}
public int GetValue(string key) {
int price = 0;
if ( !_priceMap.TryGetValue(key, out price)) {
price = 100;
}
return price;
}
}
One of the ways - you can create nested dictionary: Dictionary<string, Dictionary<string, Dictionary<string, object>>>. In your code you should split "Acme.ProductA.MinimumPrice" by dots and get or set a value to the dictionary corresponding to the splitted chunks.
Another way is using Linq2Xml: you can create XDocument with Acme as root node, products as children of the root and and attributes you can actually store as attributes on products or as children nodes. I prefer the second solution, but it would be slower if you have thousands of products.
I would take an OOP approach to this. The way that you explain it is all your Products are represented by objects, which is good. This seems like a good use of polymorphism.
I would have all products have a ProductBase which has a virtual property that defaults
virtual MinimumPrice { get { return 100; } }
And then your specific products, such as ProductA will override functionality:
override MinimumPrice { get { return 50; } }
It seems strange that the language apparently includes no suitable functionality.
I find myself with data that would best be expressed as a multi-dimensional array but it's utterly constant, there is no way anyone could want to change it without also changing the associated code. Faced with such stuff in Delphi the answer is obvious--a constant whose value is the table. However, C# doesn't seem to support anything like this.
Google shows many people griping about this, no good answers.
How do people handle this sort of situation?
(And don't say that constants don't belong in code--the last one I bumped into was all possible permutations of 4 items. Unless the very nature of spacetime changes this is set in stone.)
What happened?? There was an answer that came pretty close, I was asking about a detail and it vanished! Simply declaring an array sort of does the job--the only problem is that the array allocation is going to run every time. The one in front of me contains 96 values--how do I get it to initialize only once? Do I just have to accept scoping it far wider than it should be? (As it stands it's in one 3-line routine that's inside what amounts to an O(n^3) routine.)
ReadOnlyCollection
There's a page in in the C# FAQ about this specific thing.
They suggest using a static readonly array:
static readonly int[,] constIntArray = new int[,] { { 1, 2, 3 }, { 4, 5, 6 }};
However, be aware that this is only sort of constant - you can still reassign individual elements within the array. Also, this has to be specified on the class level since it's a static, but it will work fairly well.
You could use a readonly Hashtable. The only downside is that readonly does not prevent you from changing the value of a particular item in the Hashtable. So it is not truly const.
readonly Hashtable table = new Hashtable(){{1,"One"},{2,"Two"}};
Or an array
public readonly string[,] arry = new string[,]{{"1","2"},{"2","4"}};
Yes, you will need to declare the variable in the appropriate scope so it does not get initialized more than once.
Like they say, just add another layer of indirection. C# doesn't need to provide a specialized data structure as a language primitive, although one does, at times, wish there was a way to make any class immutable, but that's another discussion.
Now you didn't mention if you need to store different things in there. In fact you didn't mention anything other than multi-dimensional and no ability to change the values or the arrays. I don't even know if the access pattern (a single int,int,int indexer) is appropriate.
But in general, for a 3-dimensional jagged array, the following works (but it isn't pretty).
One caveat is the type you construct it with also needs to be immutable, but that's your problem. You can just create your own read-only wrapper.
public static readonly ReadOnlyThreeDimensions<int> MyGlobalThree
= new ReadOnlyThreeDimensions<int>(IntInitializer);
public class ReadOnlyThreeDimensions<T>
{
private T[][][] _arrayOfT;
public ReadOnlyThreeDimensions(Func<T[][][]> initializer)
{
_arrayOfT = initializer();
}
public ReadOnlyThreeDimensions(T[][][] arrayOfT)
{
_arrayOfT = arrayOfT;
}
public T this [int x, int y, int z]
{
get
{
return _arrayOfT[x][y][z];
}
}
}
And then you just need to provide some initializer method, or assign it in a static constructor.
public static int[][][] IntInitializer()
{
return xyz // something that constructs a [][][]
}
Enumerations, surely.
Well, I've taken the approach of the following, it's a little nasty to read but easy to edit.
public struct Something
{
public readonly int Number;
public readonly string Name;
public Something(int num, string name) { this.Number = num; this.Name = name; }
}
public readonly Something[] GlobalCollection = new Something[]
{
new Something(1, "One"),
new Something(2, "Two"),
};
If you were to have a naming system in your app where the app contains say 100 actions, which creates new objects, like:
Blur
Sharpen
Contrast
Darken
Matte
...
and each time you use one of these, a new instance is created with a unique editable name, like Blur01, Blur02, Blur03, Sharpen01, Matte01, etc. How would you generate the next available unique name, so that it's an O(1) operation or near constant time. Bear in mind that the user can also change the name to custom names, like RemoveFaceDetails, etc.
It's acceptable to have some constraints, like restricting the number of characters to 100, using letters, numbers, underscores, etc...
EDIT: You can also suggest solutions without "filling the gaps" that is without reusing the already used, but deleted names, except the custom ones of course.
I refer you to Michael A. Jackson's Two Rules of Program Optimization:
Don't do it.
For experts only: Don't do it yet.
Simple, maintainable code is far more important than optimizing for a speed problem that you think you might have later.
I would start simple: build a candidate name (e.g. "Sharpen01"), then loop through the existing filters to see if that name exists. If it does, increment and try again. This is O(N2), but until you get thousands of filters, that will be good enough.
If, sometime later, the O(N2) does become a problem, then I'd start by building a HashSet of existing names. Then you can check each candidate name against the HashSet, rather than iterating. Rebuild the HashSet each time you need a unique name, then throw it away; you don't need the complexity of maintaining it in the face of changes. This would leave your code easy to maintain, while only being O(N).
O(N) will be good enough. You do not need O(1). The user is not going to click "Sharpen" enough times for there to be any difference.
I would create a static integer in action class that gets incremented and assigned as part of each new instance of the class. For instance:
class Blur
{
private static int count = 0;
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
public Blur()
{
_name = "Blur" + count++.ToString();
}
}
Since count is static, each time you create a new class, it will be incremented and appended to the default name. O(1) time.
EDIT
If you need to fill in the holes when you delete, I would suggest the following. It would automatically queue up numbers when items are renamed, but it would be more costly overall:
class Blur
{
private static int count = 0;
private static Queue<int> deletions = new Queue<int>();
private string _name;
public string Name
{
get { return _name; }
set
{
_name = value;
Delete();
}
}
private int assigned;
public Blur()
{
if (deletions.Count > 0)
{
assigned = deletions.Dequeue();
}
else
{
assigned = count++;
}
_name = "Blur" + assigned.ToString();
}
public void Delete()
{
if (assigned >= 0)
{
deletions.Enqueue(assigned);
assigned = -1;
}
}
}
Also, when you delete an object, you'll need to call .Delete() on the object.
CounterClass Dictionary version
class CounterClass
{
private int count;
private Queue<int> deletions;
public CounterClass()
{
count = 0;
deletions = new Queue<int>();
}
public string GetNumber()
{
if (deletions.Count > 0)
{
return deletions.Dequeue().ToString();
}
return count++.ToString();
}
public void Delete(int num)
{
deletions.Enqueue(num);
}
}
you can create a Dictionary to look up counters for each string. Just make sure you parse out the index and call .Delete(int) whenever you rename or delete a value.
You can easily do it in O(m) where m is the number of existing instances of the name (and not dependent on n, the number of items in the list.
Look up the string S in question. If S isn't in the list, you're done.
S exists, so construct S+"01" and check for that. Continue incrementing (e.g. next try S+"02" until it doesn't exist.
This gives you unique names but they're still "pretty" and human-readable.
Unless you expect a large number of duplicates, this should be "near-constant" time because m will be so small.
Caveat: What if the string naturally ends with e.g. "01"? In your case this sounds unlikely so perhaps you don't care. If you do care, consider adding more of a suffix, e.g. "_01" instead of just "01" so it's easier to tell them apart.
You could do something like this:
private Dictionary<string, int> instanceCounts = new Dictionary<string, int>();
private string GetNextName(string baseName)
{
int count = 1;
if (instanceCounts.TryGetValue(baseName, out count))
{
// the thing already exists, so add one to it
count++;
}
// update the dictionary with the new value
instanceCounts[baseName] = count;
// format the number as desired
return baseName + count.ToString("00");
}
You would then just use it by calling GetNextName(...) with the base name you wanted, such as
string myNextName = GetNextName("Blur");
Using this, you wouldn't have to pre-init the dictionary.
It would fill in as you used the various base words.
Also, this is O(1).
I would create a dictionary with a string key and a integer value, storing the next number to use for a given action. This will be almost O(1) in practice.
private IDictionary<String, Int32> NextFreeActionNumbers = null;
private void InitializeNextFreeActionNumbers()
{
this.NextFreeActionNumbers = new Dictionary<String, Int32>();
this.NextFreeActionNumbers.Add("Blur", 1);
this.NextFreeActionNumbers.Add("Sharpen", 1);
this.NextFreeActionNumbers.Add("Contrast", 1);
// ... and so on ...
}
private String GetNextActionName(String action)
{
Int32 number = this.NextFreeActionNumbers[action];
this.NextFreeActionNumbers[action] = number + 1;
return String.Format("{0} {1}", action, number);
}
And you will have to check against collisions with user edited values. Again a dictionary might be a smart choice. There is no way around that. What ever way you generate your names, the user can always change a existing name to the next one you generate unless you include all existing names into the generation schema. (Or use a special character that is not allowed in user edited names, but that would be not that nice.)
Because of the comments on reusing the holes I want to add it here, too. Don't resuse the holes generated be renaming or deletion. This will confuse the user because names he deleted or modified will suddenly reappear.
I would look for ways to simplify the problem.
Are there any constraints that can be applied? As an example, would it be good enough if each user can only have one (active) type of action? Then, the actions could be distinguished using the name (or ID) of the user.
Blur (Ben F)
Blur (Adrian H)
Focus (Ben F)
Perhaps this is not an option in this case, but maybe something else would be possible. I would go to great lengths in order to avoid the complexity in some of the proposed solutions!
If you want O(1) time then just track how many instances of each you have. Keep a hashtable with all of the possible objects, when you create an object, increment the value for that object and use the result in the name.
You're definitely not going to want to expose a GUID to the user interface.
Are you proposing an initial name like "Blur04", letting the user rename it, and then raising an error message if the user's custom name conflicts? Or silently renaming it to "CustomName01" or whatever?
You can use a Dictionary to check for duplicates in O(1) time. You can have incrementing counters for each effect type in the class that creates your new effect instances. Like Kevin mentioned, it gets more complex if you have to fill in gaps in the numbering when an effect is deleted.