dealing with static list - c#

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.

Related

Public static readonly objects c#

Is there any disadvantage to using public static read-only objects in a web application? I have not used them before.
I have a web application that needs to change the display on the page depending on the user's permissions and the state of their existing action.
This is the static class which returns the custom object for their abilities.
public static class Abilities
{
public static readonly Ability ViewPage = new Ability()
{
LinkText = "something",
Hidden = false,
//Any other additional unchanging properties
}
}
Then for each user when they log in there is a method that sets the abilities that they should have
public class User
{
public List<Ability> GetMyAbilities()
{
var myAbilities = new List<Ability>();
if //some programming logic here
myAbilities.Add(Abilities.ViewPage);
return myAbilities;
}
}
This seems to be working as expected, but I wonder if there were any disadvantages or problems when using this method for multiple users?
As per comments - to add a bit of detail. The user class is created for each user when they log in to the web application. The list of abilities refers to stuff that they can do when they have logged in. Each user will therefore get a list of the abilities that they have when they log in to the Default page.

replacement for static variable

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.)

Best practice to store temporary information

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;
}
}
}

So, when one user logs in to my application, all current users become that user

I'm trying to figure out which part of my program is causing this error.
I have multiple pages that all inherit from PageBase. They get their user profile from PageBase. This is the function that gets their user name from PageBase:
uiProfile = ProfileManager.FindProfilesByUserName(CompanyHttpApplication.Current.Profile.UserName)
In the CompanyHttpApplication I have
public static CompanyHttpApplication Current
{
get { return (CompanyHttpApplication)HttpContext.Current.ApplicationInstance; }
}
and
public CompanyProfileInfo Profile
{
get
{
return profile ??
(profile =
ProfileManager.FindProfilesByUserName(ProfileAuthenticationOption.Authenticated,
User.Identity.Name).Cast
<CompanyProfileInfo>().ToList().First());
}
private set { profile = value; }
}
Unfortunately I did not write this section of the code and the programmer who did it is no longer on the project. Is there any one that can explain to me why, when another user logs in (while I am using the application), I become that user?
HttpContext.Current.ApplicationInstance is globally shared. It is not per user. Thus, you have a shared profile that is immediately overwriting whatever you originally set when your new user logs in.
The Application instance is shared across every request — the application level.
You want the Session level — each user gets their own instance.
Use HttpContext.Current.Session instead of ApplicationInstance.
(Code below renames original, and adds a property, to be more clear. Feel free to adjust as necessary.)
public static CompanyHttpApplication CurrentApplication
{
// store application constants, active user counts, message of the day, and other things all users can see
get { return (CompanyHttpApplication)HttpContext.Current.ApplicationInstance; }
}
public static Session CurrentSession
{
// store information for a single user — each user gets their own instance and can *not* see other users' sessions
get { return HttpContext.Current.Session; }
}

Dealing with allowed commands per access level?

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.

Categories

Resources