Restricting child class from accessing parent class methods - c#

I have 3 departments/classes Employee, Account and Admin.
In Employee department we have three properties -: "EmployeeID", "EmployeeName", "Salary".
Requirement-:
Account department can access all the three properties("EmployeeID", "EmployeeName", "Salary") from Employee department whereas Admin department can only access properties ("EmployeeID" ,"EmployeeName").
We have to restrict Admin Department from accessing property("Salary") from Employee Department.
How can we implement the above mentioned real life concept in C# programming.
I was trying using inheritance but could not get any solution.
class Employee
{
public int EmployeeId = 123;
public string EmployeeName = "Ram";
public double salary = 50000;
}
class Account : Employee
{
}
class Admin : Account
{
}
public class Demo
{
public static void Main(string[] args)
{
Account ac = new Account();
Console.WriteLine("EmployeeID= {0}", ac.EmployeeId);
Console.WriteLine("EmployeeName= {0}", ac.EmployeeName);
Console.WriteLine("EmployeeSalary= {0}", ac.salary);
Admin ad = new Admin();
Console.WriteLine("EmployeeID= {0}", ad.EmployeeId);
Console.WriteLine("EmployeeName= {0}", ad.EmployeeName);
// requirement is salary property should not be accesssible to the admin object;
Console.WriteLine("EmployeeSalary= {0}", ad.salary);
}
}
}

I think you are mixing up different concerns here. C# access modifiers, i.e. public/private etc, is intended to make your code more readable and modular.
Preventing Admin users from accessing "Salaries" is a business requirement that are usually not mapped directly to code. One option would be to have an account type enum:
public enum EmployeeType{
Employee,
Account ,
Admin
}
This lets you check the account type whenever you want to allow the user to do anything:
var myEmployeeType= ...
switch(myEmployeeType){
case EmployeeType.Account:
Console.WriteLine("EmployeeID= {0}", ac.EmployeeId);
Console.WriteLine("EmployeeName= {0}", ac.EmployeeName);
Console.WriteLine("EmployeeSalary= {0}", ac.salary);
break;
....
}
Note that any checks done on the local machine can probably be circumvented by a skilled user. Anything that is important for security needs to be checked and controlled on a server that you have control over. A typical solution would be a web server that does all the user management and security checks, and uses a private database for storage.

Related

Class constructor and unit tests

I have created a class Accountthat has the common fields for the account. It looks likes this:
public class Account
{
public string Name { get; set; }
public double Balance { get; set; }
public Account(double Credit)
{
Balance = Credit;
}
}
Then I created a Withdrawal class where the withdrawal take place. This withdrawal class inherits from the Account Class. I have created an interface where the withdrawal class inherits from. The main reason for having a constructor in the account class is, when a customer first opens an account with the bank, an amount must be credited into the customer's account as a form of thank you for opening an account with us. This amount is not fixed, it depends on the type of account that the customer opens.
My challenge now is anytime I am executing the withdrawal class, the constructor of the base class gets executed and the thank you gift replaces any amount the customer has in the balance.
What I really want to do is for the constructor to get executed pmce and the withdrawal class should work without the base class constructor firing up.
I will also like to know if I have violated any SOLID principle, especially in the logic method . Will I be able to unit test withdrawal1 method most especially.
This is my Withdrawal class
public class Withdrawal : Account, IAccountWithdrawal
{
public Withdrawal() : base(400)
{
}
public void Withdrawal1(double Amount)
{
bool Result = Logic(Amount);
}
public bool Logic (double Amt)
{
if (Amt <= Balance)
{
Balance -= Amt;
return true;
}
else
{
return false;
}
}
}
An object should encapsulate its own data and operations that work on this data only.
So the Account class should hold the Balance as data. As noted above, use decimal for financial calculations. It should also hide the balance from any outside manipulation that does not go through the appropriate methods, so it should be private. One could envision two methods that change the balance: Withdraw and Deposit. Because the Balance is private, we will also need a GetCurrentBalance method to read the current balance. The constructor takes all parameters that are required to create a valid new account (note that Balance will default to 0).
public class Account {
public Account(string name) {
Name = name;
}
// Name is required for a valid account, so it is part of the constructor
public string Name { get; private set; }
// Balance is critical, so it is private to prevent direct manipulation from outside
private decimal Balance { get; set; }
public decimal GetCurrentBalance() {
return Balance;
}
public void Deposit(decimal amount) {
Balance += amount;
// here would be a good place to write audit logs ...
}
public void Withdraw(decimal amount) {
if (Balance < amount) {
throw new InvalidOperationException($"The account '{Name}' can not be overdrawn.")
}
Balance -= amount;
}
}
But for many use cases, there will be more than one object involved. Let us look at the "Create new account and deposit the initial gift" use case. There are actually two accounts involved: the account to be created and the account of the bank from which the gift should be transferred.
In such cases where more than one object is involved, it is better to have a separate DomainService class that handles the business logic. This makes the code easier to understand because there are no hidden calls between the involved objects. The DomainService provides a specific method for every business case, and takes all involved objects as parameters. In our example, there is an explicit OpenNewAccount method that creates the new account and transfers the initial gift. Note that the AccountDomainService does not care how the required accountToWithdrawGift is to be retrieved, it just takes it as parameter. Also note that because we know the exact use case, we can generate meaningful error messages.
public AccountDomainService {
public Account OpenNewAccount(string name, Account accountToWithdrawGift, decimal giftAmount) {
// create the new Account
var newAccount = new Account(name);
// now handle the gift
try {
accountToWithdrawGift.Withdraw(giftAmount);
newAccount.Deposit(giftAmount);
}
catch (InvalidOperationException ex) {
throw new InvalidOperationException (
$"The account '{accountToWithdrawGift.Name}' has insufficient balance " +
$"to withdraw the gift amount '{giftAmount}'.", ex
);
}
return newAccount;
}
}
The business logic is called by an ApplicationService which faces the outside (e.g. UI, webservice). Here is a good place to validate any user inputs and handle database access.
public class AccountApplicationService {
private DbContext _dbContext;
private AccountDomainService _domainService;
// you can use Dependency Injection to provide the appropiate dbContext and domainService
public AccountApplicationService(DbContext dbContext, AccountDomainService domainService) {
_dbContext = dbContext;
_domainService = domainService;
}
public Account OpenNewAccount(OpenNewAccountCommand command) {
// validate user input ...
Validate(command);
// load bank account from the database
var accountToWithdrawGift = _dbContext.Accounts.Single(a => a.Name == "Bank Ldt.");
const decimal giftAmount = 400.00M;
// call domain service to execute the business case
var newAccount = _domainService.OpenNewAccount(command.Name, accountToWithdrawGift, giftAmount);
// persist new Account in the Database
_dbContext.Accounts.Add(newAccount);
_dbContext.SaveChanges();
return newAccount;
}
}
With this structure, the business logic encapsulated in Account and AccountDomainService can be unit tested in full without the need to mock the database. The database required by AccountApplicationService can be mocked and injected in the constructor.

Creation of domain objects

I'm creating an application with employee and employer as a domain objects.
Both of them have a reference to User object where I store password and other account related stuff.
Example:
public class Employee
{
public Guid EmployeeId { get; set; }
public User User { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string About { get; set; }
...
//other properties
}
public class Employer
{
public Guid EmployerId { get; set; }
public User User { get; set; }
public string CompanyName { get; set; }
public string CompanyDescription { get; set; }
public string FoundedYear { get; set; }
...
//other properties
}
public class User
public Guid UserId { get; set; }
public string Email { get; set; }
public string PasswordHash { get; set; }
...
//other properties
}
I'm also using application services where a method represents a single use case.
Let's say I have RegisterEmpolyee method that should save employee to database set his role to "Employee" and send verification email.
This is my code right now. I'm using AspNet.Core.Idenity.UserManager to create user account:
public async Task<EmployeeDto> RegisterEmployee(RegisterEmployeeDto employee)
{
var validateResult = _validatorService.Validate(employee);
if (!validateResult.IsValid)
throw new ServerException
("RegisterEmployeeDto is not valid", validateResult.GetErrors());
await _db.BeginTransactionAsync();
var newUser = new User { UserName = employee.Email, Email = employee.Email };
var userCreationResult = await _userManager.CreateAsync(newUser, employee.Password);
if (!userCreationResult.Succeeded)
{
var userCreationErrors = userCreationResult.GetIdentityResultErrors();
throw new ServerException("Error during create User account.", userCreationErrors);
}
await _roleService.AddUserToRoleAsync(newUser.Id, ApplicationRoles.Employee);
var verificationCode = await _userManager.GenerateEmailConfirmationTokenAsync(newUser);
newUser.VerificationCode = verificationCode;
await _emailService.SendActivationEmail(newUser.Email, newUser.Id, verificationCode);
var newEmployee = new Employee(employee.Name, employee.Surname, newUser);
await _db.Employees.AddAsync(newEmployee);
await _db.CompleteAsync();
var employeeDto = _mapper.Map<Employee, EmployeeDto>(newEmployee);
_db.CommitTransaction();
return employeeDto;
}
And here are my questions:
Does this code and my approach are fine according to DDD?
Should I extract creation of employee to domain service? Or maybe factory? And if so should I call repository method from there? (I mean service of course)
Let's say should extract creation of employee to domain service. Should I create User internally then?
Like this:
public async Task<Employee> CreateEmployee(RegisterEmployeeDto employee)
{
var newUser = new User { UserName = employee.Email, Email = employee.Email };
var userCreationResult = await _userManager.CreateAsync(newUser, employee.Password);
if (!userCreationResult.Succeeded)
{
var userCreationErrors = userCreationResult.GetIdentityResultErrors();
throw new ServerException("Error during create User account.", userCreationErrors);
}
var newEmployee = new Employee(employee.Name, employee.Surname, newUser);
//Should I call repository here?
await _db.Employees.AddAsync(newEmployee);
await _db.CompleteAsync();
return newEmployee;
}
Or maybe pass User as a parameter?
And last question: Where is a right place to checking if user I want to create exist or not? Is Application service appropriate place to do so?
Thank you in advance for answers.
From what I see, User, Employee and Employer are Aggregate roots (AR).
Does this code and my approach are fine according to DDD?
In DDD it's not recommended that an Aggregate have references to other Aggregates other than by ID. Your Employee and Employer AR have such a bad reference so it is not OK. Instead Employee and Employer should contain only a UserId field.
Should I extract creation of employee to domain service? Or maybe factory? And if so should I call repository method from there? (I mean service of course)
From what I can see you have a complex process of creating multiple Aggregates. In DDD you cannot do this atomically, inside a single transaction. Instead, every Aggregate is created/mutated in its own transaction. There is however a tactical pattern of coordinating a long process: Saga/Process manager.
You should define a process of registering an employee as a Saga: RegisterEmployee. This process should have an interface with these methods: create, start, continue. The create method receive all the data it needs to start process. The start method tries to run the individual steps (like createEmployee, createUser etc); if the start method is run again, it should continue from where has stopped, so the Saga should record its status.
The architecture can be made better by making the command on Aggregates as idempotent. In this way, when a Saga restarts it can send again all the commands to the Aggregates; this effectively makes the Saga very simple.
Let's say should extract creation of employee to domain service. Should I create User internally then?
That domain service is in fact the Saga from the previous step. The Saga however should not contain logic that belongs to the Aggregates! Be carefully to not make your domain model anaemic. The Saga should contain only coordinating logic!
And last question: Where is a right place to checking if user I want to create exist or not? Is Application service appropriate place to do so?
What means that an User already exists? There is already an user with that username? If yes, then the simplest solution is to have an unique index on the username column, if possible. If it's not possible (i.e. you have sharding enabled) then you can have another Saga that checks for duplicates and reports to an Admin or something.

Best way to do property level authorization in ServiceStack?

I'm currently developing a SPA in Angular, and so I've created a REST service using ServiceStack. I am also using ServiceStack's default authentication and authorization solution, which allows me to decorate services with the Authenticate attribute, and also allows me to authorize roles.
However, since my application has users, and users own resources, I need a way to restrict non-authorized users from performing certain actions. Furthermore, I would like to be able to create a single service for each discrete entity which can properly figure out what is safe to write to the database and what is safe to return to the user depending on their level of authorization.
So as an example, let's say I've created a service to handle operations on a Group entity. One of the actions I allow on a Group is to get the details for it:
Route: api/groups/{Id}
Response: Name, Description, CoverImageUrl, Members
However, depending on who the user is, I wish to restrict what data is returned:
Not authenticated: Name, CoverImageUrl
Authenticated: Name, CoverImageUrl, Decription
Member of requested group: Full access
Admin of website: Full access
So one simple approach to doing this is to create 3 different response DTOs, one for each type of response. Then in the service itself I can check who the user is, check on their relation to the resource, and return the appropriate response. The problem with this approach is that I would be repeating myself a lot, and would be creating DTOs that are simply subsets of the "master" DTO.
For me, the ideal solution would be some way to decorate each property on the DTO with attributes like:
[CanRead("Admin", "Owner", "Member")]
[CanWrite("Admin", "Owner")]
Then somewhere during the request, it would limit what is written to the database based on who the user is and would only serialize the subset of the "master" DTO that the user is permitted to read.
Does anyone know how I can attain my ideal solution within ServiceStack, or perhaps something even better?
The direct approach is the easiest, but you could also take advantage of custom filters attributes.
[Route("/groups/{Id}"]
public class UpdateGroup
{
public int Id { get; set; }
public string Name { get; set; }
public string CoverImageUrl { get; set; }
public string Description { get; set; }
}
[RequiresAnyRole("Admin", "FullAccess")]
[Route("/admin/groups/{Id}"]
public class AdminUpdateGroup
{
public int Id { get; set; }
public string Name { get; set; }
public string CoverImageUrl { get; set; }
public string Description { get; set; }
//... other admin properties
}
Service implementation:
public object Any(UpdateGroup request)
{
var session = base.SessionAs<AuthUserSession>();
if (session.IsAuthenticated) {
//.. update Name, CoverImageUrl, Description
}
else {
//.. only update Name, CoverImageUrl
}
}
public object Any(AdminUpdateGroup request)
{
//... Full Access
}
What ended up being the most pragmatic solution for me was actually pretty simple. The basic idea is that whichever service requires row-level authorization should implement a GetUserRole method, which in my case returns the user's most permissive role.
protected string GetUserRole(Domain.Group entity)
{
var session = SessionAs<AuthUserSession>();
var username = session.UserName;
if (session.Roles.Contains("Admin"))
{
return "Admin";
}
if (entity.Id == default(int) || entity.Leader.Username.Equals(username))
{
return "Leader";
}
// More logic here...
return session.IsAuthenticated ? "User" : "Anonymous";
}
Then I can use the user's role to figure out what to let them write:
var entityToWriteTo = ... // code that gets your entity
var userRole = GetUserRole(entityToWriteTo);
if (new[] {"Admin"}.Contains(userRole))
{
// write to admin-only entity properties
}
if (new[] {"Admin", "Leader"}.Contains(userRole))
{
// write to admin or leader entity properties
}
// Etc.
And the same logic applies for reads: You populate a DTO with properties set conditionally based on their role. Later on when you return the DTO back to the client, any properties that you haven't set either won't be serialized or will be serialized with a null value.
Ultimately, this solution allows you to use a single service for a resource instead of creating multiple services each with their own request DTO. There are, of course, refactorings you can do that makes this solution more streamlined. For example, you can isolate all of your reads and writes to one part of your code which will keep the services themselves free of role checks and things like that.

Granting an uber flexible user acess/modify rights system

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.

Creating Login/Password in C# (compare List<> to string)

Hello im trying to create a login using wcf but somehow looks like my program dont work as I wanted ;(
public class UserService : IUserService
{
[DataMember]
public string Login { get; set; }
[DataMember]
public string Password { get; set; }
[DataMember]
public string Type { get; set; }
[DataMember]
public int ID { get; set; }
public List<UserInfo> GetUserInformation()
{
QuizDBEntities contex = new QuizDBEntities();
var UserInfo = from a in contex.UserInfoes select a;
return UserInfo.ToList();
}
}
I created
protected void Button1_Click(object sender, EventArgs e)
{
string username = TextBox1.Text;
string password = TextBox2.Text;
UserService vs = new UserService();
List<UserInfo> alfa = new List<UserInfo>();
}
I used few foreach/if loop but every time I do something wrong and my list act like its empty ( I tried grindwiev and did get all data ;( ) Anyone can help me and give hint how can I compare List to login/password ?
A WCF service isn't actually a service until it's hosted somewhere (IIS, self-hosted, etc). Simply adding the attributes [ServiceContract] and [OperationContract] do not magically make it a service.
SOAP Web services like WCF are not directly accessed by the client - the client goes through a proxy to interact with the service. This proxy can be generated automatically by Visual Studio through either Add Service Reference or the command line svcutil.exe. An easy way to do this is to create a new WCF Service Application - this will be hosted in IIS. There are different (and in my opinion better) ways to host the service, but for simplicity and sake of illustration we'll go with this one.
So let's assume you have a WCF service application up and running, and it has the code you posted above. You could then choose Add Service Reference in the VS Solution Explorer to add a service reference to your service. This will generate a proxy for you to use. The name of the proxy is usually UserServiceClient (i.e., Visual Studio adds Client to the end).
To call a method in your service with this proxy, you would do this:
UserServiceClient proxy = new UserServiceClient();
List<UserInfo> users = proxy.GetUserInformation;
This would give you a list of all the users in your database. You would probably want to either markup the UserInfo entity as a DataContract, or create a new class that has the properties in it as a DataContract - your current code doesn't do anything to set the properties it has in it, and services themselves don't do anything with properties (not to mention your code isn't setting any values for them anyway).
Now for your other question - "how can I compare List to login/password"? In a nutshell, you can't. Your List<UserInfo> is a list of UserInfo objects, and you're attempting to compare a string to this list. That won't work.
What you could do, however, is create another method in your service that would accept a username and a password and return that user's information if it is found. It might look something like below, but first let's make a DataContract to hold the UserInfo (basically moving the DataMembers from the service to a separate class:
[DataContract]
public class UserInformation
{
[DataMember]
public string Login { get; set; }
[DataMember]
public string Password { get; set; }
[DataMember]
public string Type { get; set; }
[DataMember]
public int ID { get; set; }
}
public UserInformation GetUser(string userName, string password)
{
UserInformation user = new UserInformation();
using (QuizDBEntities context = new QuizDBEntities())
{
user = (from a in context.UserInfoes
where a.UserName == userName && a.Password == password
select new UserInformation() {
Login = a.UserName,
Password = a.Password,
Type = a.Type,
ID = a.ID}).SingleOrDefault();
}
return user;
}
The UserInformation class contains the DataMembers you originally had in your service. The LINQ query selects the user that has the matching UserName and Password and populates the UserInformation class (property names are conjecture as I don't know what your UserInfo entity looks like). The SingleOrDefault() at the end selects one matching result, or if no match is found returns the default value - which in this case will be null.
You could then use it like this:
UserServiceClient proxy = new UserServiceClient();
UserInformation user = proxy.GetUser("someName", "somePassword");
proxy.Close();
if (user == null)
{
// No match was found, so do something
}
else
{
// Match was found, so proceed with what you were doing
}
All of the above is primarily for illustration purposes, but you should be able to adapt to your program's needs. I would also suggest Googling for some good tutorials on how to create and host a WCF service.

Categories