restricting access to a dropdownlist in C# - c#

Hello I have a 'RestrictAccessController' That looks like this
public class RestrictAccessController : Controller
{
private PIC_Program_1_0Context db = new PIC_Program_1_0Context();
public ActionResult Index()
{
return View ();
}
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple=true)]
public class RestrictAccessAttribute : ActionFilterAttribute
{
private PIC_Program_1_0Context db = new PIC_Program_1_0Context();
public AccessRestrictions restriction { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
// here's where we check that the current action is allowed by the current user
if (!IGT.canAccess(IGT.userId, restriction, false))
{
string url = IGT.baseUrl+"/Home/NotAllowed";
string msg = "This page requires " + IGT.DisplayEnum(restriction) + " access";
filterContext.Result = new RedirectResult("~/Home/NotAllowed?msg="+HttpUtility.HtmlEncode(msg));
}
}
And a Config model that looks like this
public enum AccessRestrictions
{
[Display(Name = "Disposal Orders")]
ModifyDisposalOrder,
[Display(Name = "Admin")]
Admin
}
public class userAccess
{
[Key]
public int ID { get; set; }
public AccessRestrictions restriction { get; set; }
public bool allow { get; set; }
public int userID { get; set; }
}
public class configDetails
{
public int ID {get; set;}
public string Name {get; set;}
public string Value {get;set;}
public bool deleted {get;set;}
public DateTime updateTime { get; set; }
}
public class Config
{
public int ID { get; set; }
[Display(Name = "Configuration Date")]
public DateTime TargetDate { get; set; }
[Display(Name = "Enable Access Restrictions")]
public bool restrictAccess { get; set; }
}
What I want to do is edit what my 'ChangeStatus' dropdown looks like based on whether they have the Admin access restriction or not. Here is the controller method that I want to edit
[RestrictAccess(restriction = AccessRestrictions.ModifyDisposalOrder)]
public ActionResult ChangeStatus(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
DisposalOrder disposalOrder = db.disposalOrders.Find(id);
if (disposalOrder == null)
{
return HttpNotFound();
}
switch (disposalOrder.Status)
{
case DOStatus.Pending:
ViewBag.statusList = new List<Object>
{
new {value = DOStatus.Pending, text = "Pending"},
new {value = DOStatus.Disposed, text = "Disposed" }
};
break;
case DOStatus.Disposed:
// if(restriction = AccessRestrictions.ModifyDisposalOrder)
ViewBag.statusList = new List<Object>
{
new {value = DOStatus.Pending, text = "Pending"},
new {value = DOStatus.Disposed, text = "Disposed" }
};
//else
//{
// new { value = DOStatus.Disposed, text = "Disposed" }
// };
break;
};
return View(disposalOrder);
}
Here is my Startup file
public class LdapAuthentication
{
private string _adUser = ConfigurationManager.AppSettings["ADUserName"];
private string _adPW = ConfigurationManager.AppSettings["ADPassword"];
private string _domain = ConfigurationManager.AppSettings["ADDomain"];
public LdapAuthentication() {
}
public string authenticate(string username, string pwd)
{
using (var context = new PrincipalContext(ContextType.Domain, _domain, _adUser, _adPW)) {
//Username and password for authentication.
if (context.ValidateCredentials(username, pwd)) {
UserPrincipal user = UserPrincipal.FindByIdentity(context, username);
Internal internalUser = new Internal {
UserName = user.SamAccountName,
ContactName = user.DisplayName,
Email = user.UserPrincipalName
};
//Search if the user account already exists in the database
PIC_Program_1_0Context db = new PIC_Program_1_0Context();
Internal existing = db.Internals.Where(x => x.UserName == user.SamAccountName).FirstOrDefault();
// If it does not, create a new user account
if (existing == null) {
// add a new Internal entry for this user
existing = new Internal {
UserName = user.SamAccountName,
ContactName = user.DisplayName,
Email = user.UserPrincipalName
};
db.Internals.Add(existing);
db.SaveChanges();
// If it does exist, but some of the data does not match, update the data
} else if(existing != internalUser) {
existing.ContactName = internalUser.ContactName;
existing.Email = internalUser.Email;
db.SaveChanges();
}
return user.SamAccountName;
} else {
return null;
}
}
}
public UserPrincipal getUserPrincipal(string username)
{
using (var context = new PrincipalContext(ContextType.Domain, _domain, _adUser, _adPW))
{
return UserPrincipal.FindByIdentity(context, username);
}
}
Is it possible for me to accomplish this?

Ok, I think I understand your question now. You need to access the User's claims. MVC Controllers have this, half way, built in.
if (User.HasClaim("ClaimNameHere", "Admin"))
{
}

Solved by adding
if (IGT.canAccess(IGT.userId, AccessRestrictions.Admin, false))

Related

ASP.NET MVC 5 - How to get value Session into table data

I'm trying to get a value session and add it into a table
here is my code i tried to get value :
public ActionResult CheckOut(FormCollection form)
{
try
{
Cart cart = Session["Cart"] as Cart;
OrderPro _order = new OrderPro();//Bảng hóa đơn sản phẩm
_order.DateOrder = DateTime.Now;
_order.AddressDeliverry = form["AddressDelivery"];
_order.IDCus = Convert.ToInt32(Session["ID"]);
db.OrderProes.Add(_order);
foreach (var item in cart.Items)
{
OrderDetail _order_detail = new OrderDetail();
_order_detail.IDOrder = _order.ID;
_order_detail.IDProduct = item.product.ProductID;
_order_detail.UnitPrice = (double)item.product.Price;
_order_detail.Quantity = item.quantity;
db.OrderDetails.Add(_order_detail);
}
db.SaveChanges();
cart.ClearCart();
return RedirectToAction("CheckOut_Success", "GioHang");
}
catch
{
return Content("<script language='javascript' type='text/javascript'>alert('Đã xảy ra lỗi, vui lòng kiểm tra thông tin');</script>");
}
}
here is the code Session :
public ActionResult Login(CustomerUser cus)
{
var check = db.CustomerUsers.Where(s => s.NameUser == cus.NameUser && s.PasswordUser == cus.PasswordUser).FirstOrDefault();
if(check == null)
{
ViewBag.ErrorLogin = "Sai info đăng nhập";
return View("Index");
}
else
{
db.Configuration.ValidateOnSaveEnabled = false;
Session["NameUser"] = cus.NameUser;
Session["PasswordUser"] = cus.PasswordUser;
Session["ID"] = cus.ID;
return RedirectToAction("DichVu", "Product");
}
}
Here is the model Session ID :
public partial class CustomerUser
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public CustomerUser()
{
this.OrderProes = new HashSet<OrderPro>();
}
public int ID { get; set; }
public string NameUser { get; set; }
public string PasswordUser { get; set; }
public string PhoneUser { get; set; }
public string EmailUser { get; set; }
}
i tried to debug but i get a error like this
enter image description here

How to audit login in ASP.NET Core?

hello community I am implementing a system to audit the modifications that are made in my application carry out the process that is described in this article:
https://codewithmukesh.com/blog/audit-trail-implementation-in-aspnet-core/?unapproved=50671&moderation-hash=71700d12d4ebaf51ad9d90c4a9834324#comment-50671
but I don't know how to get the login of my application, to login I use web token and authentication provider.
any suggestion how to do it? I don't know if it can be done with serilog or something similar
this is my code:
public class Audit
{
public int Id { get; set; }
public string UserId { get; set; }
public string Type { get; set; }
public string TableName { get; set; }
public DateTime DateTime { get; set; }
public string OldValues { get; set; }
public string NewValues { get; set; }
public string AffectedColumns { get; set; }
public string PrimaryKey { get; set; }
}
public enum AuditType
{
None = 0,
Create = 1,
Update = 2,
Delete = 3
}
public class AuditEntry
{
public AuditEntry(EntityEntry entry)
{
Entry = entry;
}
public EntityEntry Entry { get; }
public string UserId { get; set; }
public string TableName { get; set; }
public Dictionary<string, object> KeyValues { get; } = new Dictionary<string, object>();
public Dictionary<string, object> OldValues { get; } = new Dictionary<string, object>();
public Dictionary<string, object> NewValues { get; } = new Dictionary<string, object>();
public AuditType AuditType { get; set; }
public List<string> ChangedColumns { get; } = new List<string>();
public Audit ToAudit()
{
var audit = new Audit();
audit.UserId = UserId;
audit.Type = AuditType.ToString();
audit.TableName = TableName;
audit.DateTime = DateTime.Now;
audit.PrimaryKey = JsonConvert.SerializeObject(KeyValues);
audit.OldValues = OldValues.Count == 0 ? null : JsonConvert.SerializeObject(OldValues);
audit.NewValues = NewValues.Count == 0 ? null : JsonConvert.SerializeObject(NewValues);
audit.AffectedColumns = ChangedColumns.Count == 0 ? null : JsonConvert.SerializeObject(ChangedColumns);
return audit;
}
}
public abstract class AuditableIdentityContext : IdentityDbContext
{
public AuditableIdentityContext(DbContextOptions options) : base(options)
{
}
public DbSet<Audit> AuditLogs { get; set; }
public virtual async Task<int> SaveChangesAsync(string userId = null)
{
OnBeforeSaveChanges(userId);
var result = await base.SaveChangesAsync();
return result;
}
private void OnBeforeSaveChanges(string userId)
{
ChangeTracker.DetectChanges();
var auditEntries = new List<AuditEntry>();
foreach (var entry in ChangeTracker.Entries())
{
if (entry.Entity is Audit || entry.State == EntityState.Detached || entry.State == EntityState.Unchanged)
continue;
var auditEntry = new AuditEntry(entry);
auditEntry.TableName = entry.Entity.GetType().Name;
auditEntry.UserId = userId;
auditEntries.Add(auditEntry);
foreach (var property in entry.Properties)
{
string propertyName = property.Metadata.Name;
if (property.Metadata.IsPrimaryKey())
{
auditEntry.KeyValues[propertyName] = property.CurrentValue;
continue;
}
switch (entry.State)
{
case EntityState.Added:
auditEntry.AuditType = Enums.AuditType.Create;
auditEntry.NewValues[propertyName] = property.CurrentValue;
break;
case EntityState.Deleted:
auditEntry.AuditType = Enums.AuditType.Delete;
auditEntry.OldValues[propertyName] = property.OriginalValue;
break;
case EntityState.Modified:
if (property.IsModified)
{
auditEntry.ChangedColumns.Add(propertyName);
auditEntry.AuditType = Enums.AuditType.Update;
auditEntry.OldValues[propertyName] = property.OriginalValue;
auditEntry.NewValues[propertyName] = property.CurrentValue;
}
break;
}
}
}
foreach (var auditEntry in auditEntries)
{
AuditLogs.Add(auditEntry.ToAudit());
}
}
}
I use a custom Controller that inherits from the built-in Controller, and added a CurrentUserName property. The problem is that Controller.User is not yet initialized in the Controller constructor. I override Controller.OnActionExecuting(), where the User exists, and use that to set my custom property.
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var authenticatedUser = User;
if (authenticatedUser != null)
{
string userId = authenticatedUser.FindFirstValue(ClaimTypes.NameIdentifier);
if (userId != null)
{
_currentUserId = int.Parse(userId, CultureInfo.InvariantCulture);
string userName = authenticatedUser.FindFirstValue(ClaimTypes.Name);
_context.CurrentUserName = userName;
_userIsAdmin = authenticatedUser.IsInRole(ConferenceRoleTypes.WebAdmin);
}
}
base.OnActionExecuting(filterContext);
}

How to Update Employee and Identity User with one to one/zero relation

I am trying to update employee record and want to update identity user too.
If i update Identity User first separately
For Example:
UserManager.Update(user);
Context.Entry(employee).State = System.Data.Entity.EntityState.Modified;
Context.SaveChanges();
and then update the employee.
maybe it is possible identity user updates with success but employee update process gets an error.
so IdentityUser is updated now but the employee is not.
how to handle this situation.
please guide.
public class Employee
{
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string AppUserId { get; set; }
[ForeignKey("AppUserId")]
public virtual AppUser AppUser { get; set; }
}
public class AppUser : IdentityUser<string, AppUserLogin, AppUserRole, AppUserClaim>, IUser<string>
{
public AppUser()
{
this.Id = Guid.NewGuid().ToString();
}
public async Task<ClaimsIdentity>
GenerateUserIdentityAsync(UserManager<AppUser, string> manager)
{
var userIdentity = await manager
.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
[Required]
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsActive { get; set; }
}
public JsonResult Create(EmployeeVM evm, AppUserVM appUser)
{
var jsonResult = new JsonResult();
jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
if (ModelState.IsValid)
{
var user = new AppUser();
evm.CreatedDate = DateTime.Now.Date;
appUser.PasswordHash = "dummypass";
user = Mapper.Map<AppUser>(appUser);
var employee = Mapper.Map<Employee>(evm);
employee.AppUser = user;
try
{
if (userService.CreateEmployee(employee))
{
jsonResult.Data = new { Success = true, message = "Success Added Record"};
}
}
catch (Exception ex)
{
jsonResult.Data = new { Success = false, message =ex.Message};
}
}
else
{
jsonResult.Data = new { Success = false, message = ModelErrors() };
}
return jsonResult;
}
public bool CreateEmployee(Employee employee)
{
Context.Employees.Add(employee);
return Context.SaveChanges()>0;
}
Adding new record works fine.
but when i update the record. i don't know how to update both records at once.
For Example:
public JsonResult Edit(EmployeeVM evm, AppUserVM appUserVM)
{
ModelState.Remove(nameof(evm.CreatedDate));
var jsonResult = new JsonResult();
jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
if (ModelState.IsValid)
{
appUserVM.UserName = appUserVM.Email;
var user = UserManager.FindById(evm.UserId);
user.Email = appUserVM.Email;
user.UserName = appUserVM.UserName;
user.FirstName = appUserVM.FirstName;
user.LastName = appUserVM.LastName;
user.IsActive = appUserVM.IsActive;
user.PhoneNumber = appUserVM.PhoneNumber;
var employee = Mapper.Map<Employee>(evm);
employee.AppUser = user;
employee.Id = evm.Id;
employee.AppUserId = user.Id;
try
{
if(userService.UpdateEmployee(employee))
jsonResult.Data = new { Success = true, message = "Success" };
}
catch (Exception ex)
{
jsonResult.Data = new { Success = false, message = ex.Message };
}
}
else
{
jsonResult.Data = new { Success = false, message = ModelErrors() };
}
return jsonResult;
}
public bool UpdateEmployee(Employee employee)
{
Context.Entry(employee).State = System.Data.Entity.EntityState.Modified;
return Context.SaveChanges() > 0;
}
Without seeing the exception, I'm not sure what the issue is, but you could trying using an attached entity and set values like the following.
var dbEmployee = Context.Emplyoees.SingleOrDefault(s => s.Id == employee.Id);
if (dbEmployee!= null)
Context.Entry(dbEmployee).CurrentValues.SetValues(employee);
The User employee service should be
public bool UpdateEmployee(Employee employee)
{
var existingEmployee = Context.Emplyoees.FirstOrDefault(s => s.Id == employee.Id);
if (existingEmployee != null)
{
//do the update to the database
Context.Entry(existingEmployee).CurrentValues.SetValues(employee);
Context.Entry(existingEmployee).State = System.Data.Entity.EntityState.Modified;
return Context.SaveChanges() > 0;
}
else return false;
}

Mapping string rules to LINQ expressions, including expressions containing own methods for authorisation

In an MVC app, I want to implement a set of rules, which super users can create, read, update and delete.
Each rule explicitly allows/forbids a user to perform an action in the format:
<Allow || Deny> userId <action_key> <condition>
The action key would be something like "DoSomeAction" as a string.
I then intend to use those rules for authorisation inside controllers for
authorisation. For example:
//GET ViewProduct/id
public ActionResult ViewProduct(string productId)
{
var product = // get product from repository;
if(RulesAuthorizer.Authorise("ViewProduct", User.Identity.GetUserId(), product){
//proceed to product... JSON or partial view, etc.
}
return new HttpStatusCodeResult(403);
}
ViewProduct is an example action_key above.
In the Authorise(string action_key, string userId, object ruleArg = null) method, I would load all the user relevant rules from the DB for this action key and decide if the user should be allowed.
However, and this is really the question, how could I use a condition for a rule as a string. For example, a condition would be:
a user must be a member of the group "Customers" and the product must not be of type "cheese" or
a custom method result such as if the product was added by group X, and group Y must not see it, I could have my method Product.GetAddedBy() and include this method in the LINQ expression.
How could I store such conditions as strings for each rule and then build LINQ expressions from them?
I intend to pass the object in question (Product in the example) in the optional ruleArg parameter.
Any ideas are much appreciated for a convenient way to store strings, which can be made into LINQ expressions at run time or any alternative approach such as perhaps map conditions to delegates with parameters?
Here is an example of user access via Attributes using strings to determine what they have access to. This is using Action/Controller to determine access but you can modify it for any string(s) you want.
Decorate the controller(s) with [AuthoriseByRole]
First the Attribute
namespace PubManager.Authorisation
{
public class AuthoriseByRoleAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var isAuthorized = base.AuthorizeCore(httpContext);
if (!isAuthorized && httpContext.Request.IsAjaxRequest())
{
httpContext.Response.StatusCode = 401;
httpContext.Response.End();
}
if (isAuthorized)
{
var request = httpContext.Request;
var r = request.RequestContext.RouteData.Values["r"]
?? request["r"];
var currentUser = (UserModel) HttpContext.Current.Session["user"];
if (currentUser == null)
{
currentUser = HttpContext.Current.User.GetWebUser();
}
var rd = httpContext.Request.RequestContext.RouteData;
string currentAction = rd.GetRequiredString("action");
string currentController = rd.GetRequiredString("controller");
if (currentUser.HasAccess(currentController, currentAction))
return true;
}
httpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return false;
}
}
}
Then the UserModel that is used to determine access:
namespace PubManager.Domain.Users
{
public class UserModel
{
public int UserId { get; set; }
public string UserName { get; set; }
public string Title { get; set; }
[Required]
[DisplayName("Forename")]
public string FirstName { get; set; }
[Required]
public string Surname { get; set; }
[Required]
[DisplayName("Company name")]
public DateTime? LastLogin { get; set; }
public bool LockedOut { get; set; }
public DateTime? LockedOutUntil { get; set; }
public bool IsGlobalAdmin { get; set; }
public bool? IsSystemUser { get; set; }
public IEnumerable<RoleModel> Roles { get; set; }
public bool HasAccess(string controller, string view)
{
if (IsGlobalAdmin || IsSystemUser.Value)
{
return true;
}
var isAuthorized = false;
if (!Roles.Any())
return false;
foreach (var role in Roles)
{
if (role.PageToRoles == null)
return false;
foreach (var pg in role.PageToRoles)
{
if (pg.RolePage.Controller.Equals(controller, StringComparison.InvariantCultureIgnoreCase) && (pg.RolePage.View.Equals(view, StringComparison.InvariantCultureIgnoreCase) || pg.RolePage.View.Equals("*")))
isAuthorized = true;
}
}
return isAuthorized;
}
}
}
Finally the GetWebUser class to get the user
namespace PubManager.Domain.Users
{
public static class SecurityExtensions
{
public static string Name(this IPrincipal user)
{
return user.Identity.Name;
}
public static UserModel GetWebUser(this IPrincipal principal)
{
if (principal == null)
return new UserModel();
var db = new DataContext();
var user = (from usr in db.Users
where usr.UserName == principal.Identity.Name
select new UserModel
{
Title = usr.Person.Title,
UserName = usr.UserName,
FirstName = usr.Person.FirstName,
Surname = usr.Person.LastName,
Email = usr.Person.Email,
LockedOut = usr.LockedOut,
UserId = usr.UserId,
IsSystemUser = usr.IsSystemUser,
IsGlobalAdmin = usr.IsGlobalAdmin.Value,
PersonId = usr.PersonId,
Roles = from r in usr.UserToRoles
select new RoleModel
{
RoleId = r.RoleId,
PageToRoles = from ptr in r.Role.PageToRoles
select new PageToRoleModel
{
RolePage = new RolePageModel
{
Controller = ptr.RolePage.Controller,
View = ptr.RolePage.View
}
}
}
}).FirstOrDefault();
if (user != null)
{
HttpContext.Current.Session["user"] = user;
}
return user;
}
}
}

how can i do access to users?

We are two classes :
First class is :
public class Team
{
public Team()
{
UsersMyTeam = new List<User>();
}
public int ID { set; get; }
public string NameTeam { set; get; }
public List<User> UsersMyTeam { set; get; }
public override string ToString()
{
return "Team";
}
}
Second class is :
public class User
{
public int ID { get; set; }
public string Name { get; set; }
public string IsActive { get; set; }
public int teamID { get; set; }
public override string ToString()
{
return "User";
}
}
I use of class by code :
protected void btnTest2_Click(object sender, EventArgs e)
{
Team myTeam = new Team();
for (int i = 0; i < 4; i++)
{
User myUser = new User();
myUser.Name = i.ToString();
myTeam.UsersMyTeam.Add(myUser);
}
myTeam.NameTeam = "asdsa";
DALTableIO DTO = new DALTableIO();
DTO.Save(myTeam);
}
I have a class named DALTableIO that save class Entrance in database :
public class DALTableIO
{
public int Add(object MyClass)
{
bool IsHaveSubClass = false;
SqlParameter[] parametrs;
List<SqlParameter> listParametrs = new List<SqlParameter>();
Type t=MyClass.GetType();
PropertyInfo[] proppertis = t.GetProperties();
foreach (PropertyInfo property in proppertis)
{
if (property.Name == "ID")
continue;
if (property.PropertyType.Name.ToLower() == "list`1")
{
IsHaveSubClass = true;
continue;
}
listParametrs.Add( new SqlParameter(property.Name, property.GetValue(MyClass, null)));
}
parametrs = new SqlParameter[listParametrs.Count];
for (int i = 0; i < listParametrs.Count; i++)
{
parametrs[i] = listParametrs[i];
}
ExecuteNonQuery(CommandType.StoredProcedure,string.Concat("Add",MyClass.ToString()),parametrs);
if (IsHaveSubClass)
{
List<object> _listTeam = GetByOption(MyClass);
Type _T1=_listTeam[0].GetType();
int _IDTeam = int.Parse(_T1.GetProperty("ID").GetValue(_listTeam[0], null).ToString());
foreach (PropertyInfo property in proppertis)
{
if (property.PropertyType.Name.ToLower() == "list`1")
{
//*****How Can Access To Users to save ****
//users are List<object>
//How do I access users.
//How do I get access to any users
}
}
}
return 1;
}
tel me how can i save user.i want send each user to Add() for save.
thanks.
Replace
if (property.PropertyType.Name.ToLower() == "list`1")
{
//*****How Can Access To Users to save ****
//users are List<object>
//How do I access users.
//How do I get access to any users
}
with
if (property.PropertyType.Name.ToLower() == "list`1")
{
IList users = property.GetValue(MyClass, null) as IList;
// users is the required list of users of Team, now loop for each user to get their Id and save to database.
foreach (var user in users)
{
//do work with user here ...
}
}

Categories