I am developing an ASP.NET MVC 4 application. userMenus is a static variable that is loaded every time a user logs in.
public class MenuCL
{
public static List<UserMenu> userMenus = new List<UserMenu>(); // the static variable
}
public class UserMenu
{
public decimal MenuID { get; set; }
public string MenuName { get; set; }
public string Controller { get; set; }
public bool Permission { get; set; }
}
I use that static variable to check whether or not the logged in user has permission to a menu/controller in a custom authorize filter.
It works fine when a single user is logged in, but when two or more users are logged-in, it's all messed up, I mean the error page("you don't have access to this page") is displayed to a user that has permission to the menu/controller.
Only now I realized it's the static variable that is causing all the trouble, after I read this :
The static variables will be shared between requests. Moreover they will be initialized when application starts, so if the AppDomain, thus application gets restarted, their values will be reinitialized.
So I need a replacement for this static variable. Anyone has any suggestion?
You can still use a static field which is a property that provides access to a session variable.
public static List<UserMenu> UserMenus
{
set
{
Session["UserMenus"] = value;
}
get
{
return Session["UserMenus"] == null ? new List<UserMenu>() : (List<UserMenu>) Session["UserMenus"];
}
}
In order to get this working on a web farm which uses a session state server (or sql server), you need to put [Serializable] attribute on top of UserMenu.
I don't think, this way you need to modify your code very much.
My question is, why do you want to use static variable? Do you want to share the values across the application? In this case you can better use session.
Updated
Assume lst as a non static List of UserMenu. Then you can use the following method to store it in session and get it bak whenever you want.
To store
Session["usemenulist"] = lst;
To get it back
try
{
lst = (List<UserMenu>)Session["usemenulist"];
}
catch
{
}
Note
If you are getting the values from the database lo load it to the List for the first time, then you can query database to get it from the database whenever you want, instead of storing it in the session. (This is another option apart from Session, you may try this way also if you want.)
When my user in the students Role login to the system, he can select various classes that he's enrolled. I already have a filter that'll redirect him to the select class page so he must select a class to access the system, and change it anytime he wants and the whole system's context will change.
As for now, i'm storing IdClass in the session variable, using the code below, and the system uses it to filter all the related queries and functions, like showing all the lessons from the current class. My question is: is this a good practice? Is this right or is there any better and efficient way? I'm trying to follow patterns.
[Serializable]
public sealed class Session
{
private const string SESSION_FOO = "STUDYPLATFORM_GUID";
private Session()
{
this.IdClass= 0; // Construct it to 0 so it evaluate as there's no Class selected.
}
/* This is the session's public IdClass that
i can get and set throughout the application. */
public int IdClass { get; set; }
public static Session Current
{
get
{
if (HttpContext.Current.Session[SESSION_FOO] == null)
{
HttpContext.Current.Session[SESSION_FOO] = new Session();
}
return HttpContext.Current.Session[SESSION_FOO] as Session;
}
}
}
I have create a permission object that stores userId, Groups user is in and user´s permissions. This is a public class
I also need to have a static object that stores a list of those permissions objects that if a administration changes anything in the permissions all changes apply immediately for every logged user
I have a couple of questions:
Should I create this static object when the first user logs in or there is a mechanism a should use to create that list before the first user log-in (For instance when we start our app on IIS)?
Would it be easy to remove the item list for a specific user when it log-out?
This is a system requirement that permissions settings take effect as soon as the administrator make changes.
Edit 1:
public class permissionTemp
{
public static Guid userGuid { get; set; }
public static string[] grupos { get; set; }
public static string[] permissoes { get; set; }
}
public static class security
{
public List<permissionTemp> userPermissionSet { get; set; }
}
Think about a singleton, so you do not worry about creation time:
Singleton:
public class Permission
{
private Permission()
{ }
private static Permission _instance = null;
public static Permission Instance
{
get
{
if(_instance == null)
{
_instance = new Permission();
}
return _instance
}
}
Now you can have access to the same instance with
Permission.Instance
The object is created at the first access. So in the private constructor you can add your code to read the permissions fom database.
You can use the Application_Start method in the global.asax to run some code when the website starts for the first time. This will run before the first request is processed.
You can use the Session_End method in the global.asax to remove the item from the list. Also you can do it at the same time where you execute FormsAuthentication.SignOut (if you use Forms Authentication).
Note: I would use some locking mechanism to prevent multiple simultaneous access to the list. An alternative place to store the list would be in the WebCache. This is used by all users, so if it is updated by person x, next read from person y will be the updated version.
First of all i recommend to avoid creating static object for storing such sensetive information and also if any user has closed browser without clicking "Log out" then object will not be removed for that particular User.
Still if you need to do this to meet your requirement you can create it in that object in Applciation Start Event on Global.asax file when application start first time.
I have a set of commands like:
.kick
.unban
.ban
.unvouch
.vouch
.add
.del
.say
Those commands are used in a chat room where I have several users with different access, for example:
Admin is allowed to use all commands.
Moderator is allowed to use .kick, .vouch .unvouch .say
Vip is allowed to use .say
Basic cannot use any command
When a command is used it goes to a bot that is present in the room, that bot will them verify the user, access and everything before performing the command.
Initially I have a user class assigned to a list:
public class Users
{
public string Name { get; set; }
public string Comments { get; set; }
public string Access { get; set; }
}
public List<Users> userList = new List<Users>();
Now I want to implement an easy way to query/check/verify if a given user has access to use a given command, but I am not sure on how to approach it.
I was thinking about having a second class assigned to a list something like the this:
public class UserAccess
{
public string AccessLevel { get; set; }
public List<string> Commands = new List<string>();
}
public List<UserAccess> accessList = new List<UserAccess>();
And query it with something like:
var user = userList.Find(x => x.Name == currentUser);
if (user != null && accessList.Exists(x => x.AccessLevel == user.Access && x.Commands.Contains(str_cmd))
{
// use the command
}
else
{
// cannot use the command
}
As I mentioned above, I have a background worker that is constantly reading the chat messages to capture when a user has typed a command which will then verify and process everything in a queue.
Registered users and access level are filled from my website API which returns JSON to my application when it starts and updates data every now and then when major commands are issued.
This is just an example, I could be over thinking the idea but I did like to hear some advices and ideas of how I could deal with this ?
You can try something like this. Although you may want to define your access list through a Db or through attributes/properties on where your actual commands are defined.
public class User
{
public static readonly UserAccess[] AccessList = {
new UserAccess() { AccessLevel = "Admin",
Commands = {".kick",".ban",".unban"}
},
new UserAccess() { AccessLevel = "User",
Commands = {".add",".del"}
},
new UserAccess() { AccessLevel = "Vip",
Commands = {".say"}
}};
public string Name { get; set; }
public string Comments { get; set; }
public string Access { get; private set; } //Assuming you can't modify this so we add the next property
public UserAccess AccessLevel { get; private set; }
public User(string access)
{
this.Access = access;
this.AccessLevel = AccessList.FirstOrDefault(x => x.AccessLevel == access);
}
}
public class UserAccess
{
public string AccessLevel { get; set; }
public List<string> Commands = new List<string>();
public bool HasCommand(string command)
{
return this.Commands.Any(x => x == command);
}
}
looks like an IRC bot or services application. the "usual" approach for this is to have a list of commands/privileges with an int representing the needed access level, and a list of users with the corresponding access-level ... whenever a command/privilege is used, try to get the users accesslevel from the list, or a default value (0) if the user is not on the list. then compare that value to the value of the used command/privilege
advantage: rather easy to implement
disadvantage: restricts commands/privileges levels to be somewhat hierarchical
alternative that would allow arbitrary complex permissions:
used Types:
User - represents a user
Group - represents a group of User-Objects
Context - represents the context of the ruleset (in terms of IRC this could be a channel)
Privilege - represents a privilege or command that can be used
Permission - says that a Privilege is either granted or denied
User- and Group-Objects can be associated with a list of Permissions by the context
a context stores a list of effective permissions for users that hold permissions in this context, or Users that are members of groups that hold permissions in this context. those effective permissions are determined the following way:
for each user itterate all group memberships
for each group itterate all permissions
if the permission is denying a Privilege, add this privilege as denied to the effective permissions of this user, overwriting any permission for this privilege that may already be present in that list
else, if the permission is granting a privilege add it to the effective permissions only if no permission for this privilege is present in the list
finally itterate over the users permissions
add the permission to the effective permissions list, overwriting any permission for this privilege that may already be present in the list.
all privileges get a default permission, initialized as "denied" (stored in the context)
when permissions are changed at runtime, the effective permissions are to be rebuilt.
when the system has to check a permission, it looks up the user and eventually does authentication. if the user is authenticated, the effective permissions are looked up by the context. if effective permissons are found for that user, the requested privilege is looked up, and the corresponding permission is checked. if we either get granted or denied, the check is completed. if no permission is found, the default permission for that privilege is used.
In an application I'm building I had an enumeration of account statuses:
public enum AccountStatus
{
Active = 1,
Trial = 2,
Canceled = 3
}
However, I needed more information from an AccountStatus so I made a class which has a few extra useful properties:
public class AccountStatus
{
public int Id {get; set;}
public string Description {get; set;}
public bool IsActive {get; set;}
public bool CanReactivate {get; set;}
}
This class get populated from a database table that might look like this:
1, "Active", True, True
2, "Trial", True, True
3, "ExpiredTrial", False, True
4, "Expelled", False, False
This is really handy when I have a customer object that uses the AccountStatus because I can write code like:
if(customer.Status.CanReactivate) // Show reactivation form
However, I have lost something equally important. I can no longer do this:
if(customer.Status == AccountStatus.Active) // allow some stuff to happen
What would be the best way, if its even possible, to include something that will allow me to mimic the enumeration within the class. I know that I could add public static fields to the AccountStatus class, but ultimately this doesn't work because if the database changes the code would have to be manually updated. By this, I mean:
public static readonly AccountStatus Active = new AccountStatus(1);
public static readonly AccountStatus Trial = new AccountStatus(2);
// etc, etc ...
I imagine there is probably a pattern for this somewhere, I just don't know what its called.
Any ideas?
CLARIFICATION
Based on the answers so far I need to clarify a couple of things.
The table above is a brief example. In my actual table there a many records, I have 12 in there right now. Plus we can add more or remove some existing. This is what I meant by "dynamic" in my question title.
Secondly, I gave a very simple use case for the ability I lost which apparently confused matters. Here is another real example:
if(customer.Status == AccountStatus.Trial || customer.Status == AccountStatus.ExpiredTrial)
... neither Trial nor ExpiredTrial are boolean values on the property. I don't want to add them either. That would set an even worse precedent than the one I'm trying to avoid (meaning I would have to add a new property to the class every time I added a new record to the table).
UPDATE
I selected an answer which didn't really meet was I was looking for, but suggests that I was looking for something unnecessary. After thinking about this, I concur. While adding an enum or static fields does duplicate some work (ie, having the values in both code and in a table) I think the benefits outweigh the negatives.
But why can't you use the enumeration as a property of that class..?
public enum State
{
Active = 1,
Trial = 2,
Canceled = 3
}
public class AccountStatus
{
public int Id {get; set;}
public State State {get; set;}
public string Description {get; set;}
public bool IsActive {get; set;}
public bool CanReactivate {get; set;}
}
And then:
if(customer.Status == AccountStatus.State.Active) // allow some stuff to happen
Rather than working with a strongly-typed enum, you could just do comparisons using a string:
public static readonly AccountStatus Active = new AccountStatus("Active");
or load the type from your database:
public static readonly AccountStatus Trial = new AccountStatus( reader["StatusField"] );
You can then do explicit comparisons:
if(customer.Status == "Active")
You lose the strong typing, but that's what dynamic means :-). You can store the known string values in constants to get some of this back.
edit
You could of course do this using the corresponding integer values, like you hinted at the end of your post. But strings are easier to read, and in this case using integers doesn't offer any sort of typing benefits.
I think you could achieve this by using a Flags enumeration where you can combine values:
[Flags]
public enum AccountStatus
{
Expelled = 1,
Active = 2,
CanReactivate = 4,
Canceled = 8,
Trial = Active | CanReactivate,
ExpiredTrial = CanReactivate,
}
However, it feels as if those different enum values move along different scales (some describe state, some describe valid actions), so it might not be the right solution. Perhaps you should instead split it into two enums.
I don't understand why you can't just write:
if (customer.Status.IsActive)
if you do/want something like this in your application:
if(customer.Status ==
AccountStatus.Active)
You have to know in your code that "Active" is a possible status. How else would you be able to write the actual word Active in your code. The status object can be dynamic, but the rest of the program that uses the status has to know what types of status exist in order to do something useful with it. What if active doesn't exist anymore, the status object may not need to be reimplemented, but the code that uses it does.
If every kind status is fully defined by parameters like it almost seems (active and trail have the same parameters, so more are needed to differentiate (expiration date?)), then check those parameters.
If a combination of parameters has to have a name, then make some kind of lookuptable where you can translate the name into its associated parameters, or its inverse. That way the name can be dynamic for that piece of code, and the parameter values are to upto some degree.
A possible real dynamic solution would be to implement some sort of scripting language/xml file/... that enables the user to specify the kinds of status, their parameters, and associate them with system behavior.
I still think your best bet is to add your missing cases to the class.
public class AccountStatus
{
public int Id {get; set;}
public string Description {get; set;}
public bool IsActive {get; set;}
public bool CanReactivate {get; set;}
public bool Trial {get; set;}
public bool ExpiredTrial {get; set;}
}
Which you can call in a simpler form than your example:
if(customer.AccountStatus.Trial || customer.AccountStatus.ExpiredTrial)
If you need to check a UserDefined status, expose that as a separate property:
public AccountStatusCode Status {get; set;}
...and call it like this:
if(customer.Status == AccountStatus.Active)
You can still add a constructor to it if you want to set an initial status.
You could make a many-to-many relationship between AccountStatus and Description. This way you can, at runtime, load all the different Descriptions you got, and then compare against those, using some sort of enumeration :)
This code does what you described in your post. I didn't code CanReactivate because you didn't say what the logic for that was.
public enum AccountStatusCode
{
Active = 1,
Trial = 2,
Canceled = 3
}
public class AccountStatus
{
private AccountStatusEnum status
//
// Constructor sets initial status.
public AccountStatus(int status)
{
this.Status = (AccountStatusCode)status;
}
public int Id { get; set; }
public string Description { get; set; }
//
//
public bool IsActive
{
get { return status == AccountStatusCode.Active; }
}
public bool CanReactivate { get; set; }
}
Note that, since you said you wanted to specify the initial account status as an int, I accept an int in the constructor, but then I cast it to an AccountStatusEnum for assigning it to the member variable. That's probably not the best practice...You should pass the constructor an AccountStatusCode value.
OK, well if you're working in C# 3.0, you could try extension methods:
// Define extension method like this:
public static bool IsActive(this AccountStatus status)
{
get { return status == AccountStatusCode.Active; }
}
//
// Call it like this:
if (AccountStatus.IsActive())
That keeps it out of your class.
I think what judo tried to explain is - a new status in the DB will require to put checking s for that new status in the conditional blocks. I think I am also doing something same. Only thing I am doing is I am also using another 'rank' field so that I can do range comparison instead of hard coding all the statuses.
For example instead of doing:
if(customer.Status == AccountStatus.Trial || customer.Status == AccountStatus.ExpiredTrial)
if I could put them in order I could do:
if(customer.Status < AccountStatus.Trial) as in our enum we can put them as ordered. So a new status in a new page wont break the other page's logics (depends on the rank of the status).