Granting an uber flexible user acess/modify rights system - c#

I am developing an application where the client needs and extremely flexible user rights system. For example, a user should be able to have update rights in Form A but not in Form B (which prevents me from defining broad update rights). Admin should also be able to transfer specific rights to a user.
I was thinking of using the Command Pattern with CanExecute method but not really sure how I can use it in such a dynamic/specific way. Any suggestions ?

I have a similar situation in my application, which can be extended via plugins and the plugins can bring in their own permission. I solved that the following way:
static/common PermissionManager
very module/form/plugin can register its available permissions in the manager
the "permission manager UI" lists all available permissions and lets the admin assign them to users
on access every module/form/plugin asks the manager if the current user has the permission
Simplified class structure:
public class PermissionManager
{
public static Dictionary<string, IEnumerable<string>> AvailablePermissions { get; set; }
public static bool? Can(User user, string permission)
{
// check DB
return DENIED ? false : (ALLOWED ? true : null);
}
}
public class MyPlugin : IPlugin
{
public void Init()
{
PermissionManager.AvailablePermissions["MyPlugin"] =
new List<string>() { "Permission1", "Permission2" };
}
public void DoWork()
{
if (PermissionManager.Can(user, "Permission1") != true)
throw new NotAllowedException();
// do work
}
}
This is the basic patter I use. Of course you should use constants or similar for the permission names/keys. The admin UI can then iterate AvailablePermissions in the configuration UI.
In the DB I have something like the following (EF Code-First):
public class UserProfilePermissions
{
public UserProfile User { get; set; }
public Permission Permission { get; set; }
public bool IsAllowed { get; set; }
}
public class Permission
{
public int Id { get; set; }
public string Key { get; set; }
public string Group { get; set; }
}
So for every permission there is one Permission entry created (on the first assignment) in the DB and mapped via the mapping table using the IsAllowed to define "ALLOWED" or "DENIED".
The null value defines a not set permission so default values can be used (=> not set permission does not always say "DENIED").
The mapping table can also be used in the same style for e.g. roles.

Related

Custom Attribute For Class Library Classes and Functions in C#

I'm developing 3rd party API connector bridge in class library NOT in ASP.NET.
User Levels
API has 3 user levels, lets say:
UserGoer
UserDoer
UserMaker
Service Restriction
Each API operation can work with one or multiple user level roles. For example, lets assume operations and reachable user levels as follows;
JokerService (reachable by UserGoer, UserMaker)
PokerService (reachable by UserGoer, UserDoer)
MokerService (reachable by UserGoer, UserDoer, UserMaker)
If UserDoer requests for JokerService, API returns bad request. JokerService is only reachable for UserGoer and UserMaker. So, I want to restrict and throw an exception.
User Token Structure
public interface IToken
{
string AccessToken { get; set; }
string RefreshToken { get; set; }
}
public class AuthenticationToken : IToken
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("refresh_token")]
public string RefreshToken { get; set; }
}
public class UserGoerAuthenticationToken : AuthenticationToken
{
}
public class UserDoerAuthenticationToken : AuthenticationToken
{
}
public class UserMakerAuthenticationToken : AuthenticationToken
{
}
Enum
public enum TokenType
{
Undefined = 0,
UserGoer = 1,
UserDoer = 2,
UserMaker = 3
}
Customized Authentication Attribute
public class AuthenticationFilter : Attribute
{
public TokenType[] TokenTypes { get; private set; }
public AuthenticationFilter(params TokenType[] TokenTypes)
{
this.TokenTypes = TokenTypes;
}
}
Example Service
[AuthenticationFilter(TokenType.UserGoer, TokenType.UserMaker)]
internal class JokerService : BaseService<JokerEntity>
{
public JokerService(IToken AuthenticationToken) : base(AuthenticationToken)
{
var tokenTypes =
(typeof(JokerService).GetCustomAttributes(true)[0] as AuthenticationFilter)
.TokenTypes;
bool throwExceptionFlag = true;
foreach (var item in tokenTypes)
{
// Check AuthenticationToken is UserGoer or UserMaker by StartsWith function
if (AuthenticationToken.GetType().Name.StartsWith(item.ToString()))
{
throwExceptionFlag = false;
break;
}
}
if (throwExceptionFlag)
throw new Exception("Invalid Authentication Token");
}
public JokerEntity Create(RequestModel<JokerEntity> model) => base.Create(model);
public JokerEntity Update(RequestModel<JokerEntity> model) => base.Update(model);
public JokerEntity Get(RequestModel<JokerEntity> model) => base.Get(model);
public List<JokerEntity> List(RequestModel<JokerEntity> model) => base.List(model);
}
In summary, JokerService can be executable by UserGoer and UserMaker. UserDoer has no permission for this service.
As you see the the usage of AuthenticationFilter attribute, I'm getting custom attributes in the constructor, because i want to know what IToken is. If there is an irrelevant "User Authentication Token" type that is passed as parameter (IToken), program should be throw an exception.
This is my solution, do you think is there any best practice for my problem?
Thank you for your help.
Interesting question. My initial thought at constructive critique would be that the tokens accepted by a particular class via the attribute is something decided at compile time and is unable to change. But, the checking for permissions is happening on the construction of each object.
You can prevent this with a static constructor that sets the tokenTypes variable. Static constructors always run before instance constructors. This is also a good place to ensure that tokenTypes is never null (in the absence of your custom attribute).
Likewise, the looping through tokenTypes can probably be a function that takes in an IToken and the tokenTypes, and more importantly, could probably live in the BaseService.cs. Writing that logic once will make it easier to maintain when some future requirement necessitates its change. :)
See also: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
Hope this helps.

Too Many Dependency Inject

I currently have a class with around 40 dependency injection. It is a hard to maintain and unit test. I am not sure a good way around.
The code is done for any type of application process that is needed to process (New License, License Renewal, Student Registration, ...), there are around 80 different types applications and what sections are associated with each application type is determined by a database table.
I have a class with all of the possible properties, there are a several more than listed but you should get the idea. Each the properties have their own set of properties that are basic data types or object pointing to other classes.
class Application
{
[JsonProperty(PropertyName = "accounting")]
public Accounting Accounting { get; set; }
[JsonProperty(PropertyName = "application")]
public Application Application { get; set; }
[JsonProperty(PropertyName = "applicationType")]
public ApplicationType ApplicationType { get; set; }
[JsonProperty(PropertyName = "document")]
public List<Attachment> Document { get; set; }
[JsonProperty(PropertyName = "employment")]
public List<Employment> Employment { get; set; }
[JsonProperty(PropertyName = "enrollment")]
public Enrollment Enrollment { get; set; }
[JsonProperty(PropertyName = "individualAddressContact")]
public IndividualAddressContact IndividualAddressContact { get; set; }
[JsonProperty(PropertyName = "instructors")]
public List<Instructor> Instructors { get; set; }
[JsonProperty(PropertyName = "license")]
public License License { get; set; }
[JsonProperty(PropertyName = "licenseRenewal")]
public LicenseRenewal LicenseRenewal { get; set; }
[JsonProperty(PropertyName = "MilitaryService")]
public List<MilitaryService> MilitaryService { get; set; }
[JsonProperty(PropertyName = "paymentDetail")]
public PaymentDetail PaymentDetail { get; set; }
[JsonProperty(PropertyName = "photo")]
public List<Attachment> Photo { get; set; }
[JsonProperty(PropertyName = "portal")]
public Portal Portal { get; set; }
[JsonProperty(PropertyName = "section")]
public List<Section> Section { get; set; }
[JsonProperty(PropertyName = "testingCalendar")]
public TestingCalendar TestingCalendar { get; set; }
[JsonProperty(PropertyName = "testingScore")]
public List<TestingScore> TestingScore { get; set; }
[JsonProperty(PropertyName = "USCitizen")]
public USCitizen USCitizen { get; set; }
}
So this class is sent/received to an Angular 10 front end using Web API's.
When an application is requested the sections and the different properties are initiated and if the application has be started the progress will be reloaded. So it is possible some of properties will be pulled from the database and sent to the Angular app.
So I have something such as
Load(applicationTypeId, applicationId)
{
Get the sections for the application type
For each section in the sections
switch sectionid
case Documents
Load all of the documents required for the application type and get any documents uploaded
case Accounting
Load the payment details, if no payment made calculate the payment
case IndividualAddressContact
Load the person name/address/contact and set a few defaults if the person hasn't started.
.....
next
}
Save()
{
Save the application
switch current section
case Documents
Save all of the documents for the application
case Accounting
Save the payment details for the application
case IndividualAddressContact
Save the person name/address/contact for the application
.....
get the next section
Update the application current section
}
I have put all of the items in the switch into their own classes but in the end I still have 1 point for serialization/deserialization and still end up with to many dependencies injected. Creating a unit test with over 40 dependencies seems hard to maintain and given I won't know which properties will/won't used until an application is requested and loaded from database. I am unsure how to get around the switch, without at some point and time having to have all of the dependencies injected into 1 class.
I would appreciate some ideas of how to get around this.
"I currently have a class with around 40 dependency injection..." - Oh my gosh!
"It is a hard to maintain and unit test..." - I don't doubt that in the least!
SUGGESTED REFACTORING:
Create a class that manages "Applications" (e.g. "ApplicationManager").
Create an abstract class "Application".
One advantage of "abstract class" over "interface" here that you can put "common code" in the abstract base class.
Create a concrete subclass for each "Application" : public class NewLicense : Application, public class LicenseRenewal : Application, etc. etc.
... AND ...
Use DI primarily for those "services" that each concrete class needs.
I'll bet the constructors for your individual concrete classes will only need to inject three or four services ... instead of 40. Who knows - maybe your base class won't need any DI at all.
This is actually a design we're actually using in one of our production systems. It's simple; it's robust; it's flexible. It's working well for us :)
I would recommend using convention over configuration principle, with the Service Locator.
Declare something like IApplicationHandler interface in your program, e.g.
public interface IApplicationQueryHandler
{
Application Populate(Application application);
}
public interface IApplicationSaveHandler
{
Bool Save(Application application);
}
Then, write pieces of your code, with dependencies and such, e.g.
public class AccountingApplicationQueryHandler : IApplicationQueryHandler
{
public Application Populate(Application application) {
//// Load the payment details, if no payment made calculate the payment
return application;
}
}
public class AccountingApplicationSaveHandler : IApplicationSaveHandler
{
public Bool Save(Application application) {
//// Save the payment details for the application
return true; // this just flags for validation
}
}
// repeat for all other properties
Then in your controller, do something like
public class ApplicationController: Controller
{
public readonly IServiceProvider _serviceProvider;
public ApplicationController(IServiceProvider sp) {
_serviceProvider = sp;
}
public Application Load(string applicationTypeId, string applicationId)
{
var application = new Application(); // or get from db or whatever
var queryHandlers = _serviceProvider.GetServices(typeof(IApplicationQueryHandler));
foreach(var handler in queryHandlers) {
application = handler.Populate(application);
}
return application;
}
[HttpPost]
public bool Save(Application application)
{
var result = true;
var saveHandlers = _serviceProvider.GetServices(typeof(IApplicationSaveHandler));
foreach(var handler in queryHandlers) {
result = handler. Save(application);
}
return result;
}
}
You would need to register your handlers, which you can do e.g. like so:
var queryHandlers = Assembly.GetAssembly(typeof(IApplicationQueryHandler)).GetExportedTypes()
.Where(x => x.GetInterfaces().Any(y => y == typeof(IApplicationQueryHandler)));
foreach(queryHandler in queryHandlers) {
services.AddTransient(typeof(IApplicationQueryHandler), queryHandler);
}
// repeat the same for IApplicationSaveHandler
Now finally, you can write unit tests for part of the code like so
[TestClass]
public class AccountingApplicationQueryHandlerTests
{
[TestMethod]
public void TestPopulate()
{
// arrange
var application = new Application();
var handler = new AccountingApplicationQueryHandler(); // inject mocks here
// act
var result = handler.Populate(application);
// Assert
Assert.AreEqual(result. PaymentDetail, "whatever");
}
}
And you can test that your controller calls the right things by mocking IServiceProvider and injecting that with a couple of dummy handlers to confirm they are called correctly.
Following zaitsman's answer you also could create AggregatedApplicationQueryHandler and AggregatedApplicationSaveHandler and pass collection of concrete implementation of IApplicationQueryHandler and IApplicationSaveHandler to its constructor.
Then you don't need foreach loop inside controller(you loop over handlers inside aggregated handler) and always have only one handler passed to controller. Passing its by constructor parameter shouldn't be so much painful.
You also could create facade over some small services and aggregate theirs functions into one bigger facade service.

How to save username in global variable asp

I have online exam system I want to save username in global variable or any other thing that just can save it.
I want this username for get and set data on SQL database.
I'm using a global variable in class but it replace in every login.
any way to save username foreach user?
public class GVar
{
public static string user
{
get; set;
}
public static string mail
{
get;
set;
}
public static string melli
{
get;
set;
}
public static bool go
{
get;
set;
}
public static System.Threading.Thread thread { get; set; }
}
Use Application or Session as the case may be.
Session variables are global but limited to current session (call it user for understanding).
Application variables are globally shared across all sessions.
So, following statements may be used to get/set variables at application level
Application["user"] = "abc"; //sets the value at application level
var user = Application["user"]; //gets the value stored at application level
Similarly, to make it global, but isolate at session level,
Session["user"] = "abc"; //sets the value at session level
var user = Session["user"]; //gets the value stored at session level
EDIT
For ease of use, I prefer implementing them as properties, somewhat like this:
Define the class with custom getter/setter properties, and add it to App_Code folder
public static class GVar
{
public static string user
{
get { return Session["GVar_User"]; }
set { Session["GVar_User"] = value; }
}
//...
}
Use it in your application, as you would normally do with any other property.
GVar.user = "abc"; //set value
var usr = GVar.user; //get value
You can save it on login like this:
Session["user"] = "gamesdl";
And then you can get the value during executing like this:
String username = (string)(Session["user"]);
You can use claims.
The claims are in identity. And you can config then in login action.

Authorization in ASP.NET MVC 4

I have a menu in web site. I want to access this for every role .
For example : i have 3 role that Role1 have access to personnel, referred, visit menu, and role2 have access to personnel, diet menu , and role3 have full access.
I created a static class that set value when user login in site. and use this class property for show/hide menu. but change this value when a nother user is login in site.
public static class GlobalVariables
{
public static string UserName { get; set; }
public static string Image { get; set; }
public static bool IsAuthorizePersonnel { get; set; }
public static bool IsAuthorizeReferred { get; set; }
public static bool IsAuthorizeDiet { get; set; }
public static bool IsAuthorizeVisit { get; set; }
}
How do i set access for menu ?
The static class is changing when new users login because ASP.NET handles multiple requests/clients in the same App domain, which means they share static classes/properties.
In order to make something like this work you would need to cache the information either via session state or a user keyed memory cache (such as Redis).
Alternatively, Asp.Net simple membership does have role support, so you could also consider creating the IsX properties as wrappers around role checks.
See the following articles for some examples:
http://www.asp.net/web-pages/overview/security/16-adding-security-and-membership
http://msdn.microsoft.com/en-us/library/5k850zwb%28v=vs.140%29.aspx
Hide link based on Role
Basically you have a single instance of the class which is used for all users in the site. Due to it being a static class.
You should create an instance-per-user class. Which you could place inside the cache under fi username.

C# some sort of plugin system

I am a mobile web developer and trying to monetize my traffic with mobile ad services and i have a problem.
First of all to get most of out of your ads you usually need to do server side request to advert company's servers and there are quite few ad services. Problem starts when you want to use them in one site.
All have different approaches to server side calls and trying to maintain and implement those ad codes becomes pain after a while.
So I decided to write a class system where i can simply create methods for every company and upload it to my site.
So far i have
public Advert class
public AdPublisher class with GetAd method that returns an Advert
public Adservice class that has Service names as enum
I also have converted server request codes of all ad services i use to classes.
It works ok but I want to be able to create an ad service class upload it so that asp.net app can import/recognize it automatically like a plugin system.
As I am new to .net I have no idea where to start or how to do it.
To make thing clear here are my classes
namespace Mobile.Publisher
{
public class AdPublisher
{
public AdPublisher()
{
IsTest = false;
}
public bool IsTest { get; set; }
public HttpRequest CurrentVisitorRequestInfo { get; set; }
public Advert GetAd(AdService service)
{
Advert returnAd = new Advert();
returnAd.Success = true;
if (this.CurrentVisitorRequestInfo == null)
{
throw new Exception("CurrentVisitorRequestInfo for AdPublisher not set!");
}
if (service == null)
{
throw new Exception("AdService not set!");
}
if (service.ServiceName == AdServices.Admob)
{
returnAd.ReturnedAd = AdmobAds("000000");
}
return returnAd;
}
}
public enum AdServices
{
Admob,
ServiceB,
ServiceC
}
public class Advert
{
public bool Success { get; set; }
public string ReturnedAd { get; set; }
}
public partial class AdService
{
public AdServices ServiceName { get; set; }
public string PublisherOrSiteId { get; set; }
public string ZoneOrChannelId { get; set; }
}
private string AdmobAds(string publisherid)
{
//snip
return "test"
}
}
Basically i want to be able to add another ad service and code like
private string AdmobAds(string publisherid){
}
So that it can be imported and recognised as ad service.
I hope i was clear enough
Ths seems like a pretty vague/general question, and considering you mentioned you're no too familiar with .NET, I thought I'd point you in the direction of the Managed Extensibility Framework. This is an official Micrsoft library designed for creating plugin/add-in systems (it's like a specialised Inversion of Control framework). Note that in .NET 4.0, it's actually part of the framework base class library. There's also a great MSDN page on Add-ins and Extensibility - relating to the System.AddIn namespace - which you may find pretty helpful too.
You can load assemblies dynamically, then query the list of classes and check whether the class is derived from your interface. Check the "Assembly" class.

Categories