I am using Csla 4.1.0 and seem to be having a cast issue. This is the same scenario as the OP in the linked thread where I am trying to get to custom properties that have been implemented into my CustomIdentity class.
When I try to cast Csla.ApplicationContext.User.Identity to CustomIdentity, I get "Unable to cast object of type 'System.Security.Principal.GenericPrincipal' to 'DMS.Library.Security.CustomIdentity.'
var identity = (CustomIdentity)Csla.ApplicationContext.User.Identity;
I thought I followed the ebook pretty well and in fact everything seems to be working. The only thing I want to get access to now is the Identity properties so that I can replace individual database calls with data that's already been loaded into my custom properties.
Let me know if there is any other information I can provide.
public static void BeginLogin(string username, string password, Action<Exception> completed) {
DMS.Library.Security.CustomIdentity.GetCustomIdentity(username, password, (o, e) => {
Csla.ApplicationContext.User = new CustomPrincipal(e.Object);
/// NOT IMPLEMENTED - Attempts to login the user with their username and password
/// As of 05/07/2015, this function is not used because it will create a circular execution of code.
/// Validation of credentials is handled within the ValidateUser function of each implemented Membership provider.
/// Assuming the ValidateUser function returns true, the Principal's Load function is used instead
throw new NotImplementedException("The CustomPrincipal Login method has not been implemented. Refer to the remarks section of method's code for an explanation.");
//var identity = DMS.Library.Security.CustomIdentity.GetCustomIdentity(username, password);
var identity = DMS.Library.Security.CustomIdentity.GetCustomIdentity(username);
/// Replaces the current CustomPrincipal object with a new one that has an UnauthenticatedIdentity loaded up.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla;
using Csla.Security;
using Csla.Serialization;
using DMS.Library.Admin;
namespace DMS.Library.Security {
[Serializable]
public class CustomIdentity : CslaIdentityBase<CustomIdentity> {
#region Properties
public static readonly PropertyInfo<string> EmailProperty = RegisterProperty<string>(c => c.Email);
/// <summary>
/// The user's E-mail
/// </summary>
public string Email {
get { return GetProperty(EmailProperty); }
private set { LoadProperty(EmailProperty, value); }
}
public static readonly PropertyInfo<Guid> UserIdProperty = RegisterProperty<Guid>(p => p.UserId);
/// <summary>
/// The user's internal identifier
/// </summary>
public Guid UserId {
get { return GetProperty(UserIdProperty); }
private set { LoadProperty(UserIdProperty, value); }
}
public static readonly PropertyInfo<string> FirstNameProperty = RegisterProperty<string>(c => c.FirstName);
/// <summary>
/// The user's first name
/// </summary>
public string FirstName {
get { return GetProperty(FirstNameProperty); }
private set { LoadProperty(FirstNameProperty, value); }
}
public static readonly PropertyInfo<string> LastNameProperty = RegisterProperty<string>(c => c.LastName);
/// <summary>
/// The user's last name
/// </summary>
public string LastName {
get { return GetProperty(LastNameProperty); }
private set { LoadProperty(LastNameProperty, value); }
}
public static readonly PropertyInfo<string> FullNameProperty = RegisterProperty<string>(c => c.FullName);
/// <summary>
/// The user's full name
/// </summary>
public string FullName {
get { return GetProperty(FullNameProperty); }
private set { LoadProperty(FullNameProperty, value); }
}
public static readonly PropertyInfo<string> HomeOrgStringProperty = RegisterProperty<string>(p => p.HomeOrgString);
/// <summary>
/// The user's Home OrgString
/// </summary>
public string HomeOrgString {
get { return GetProperty(HomeOrgStringProperty); }
private set { LoadProperty(HomeOrgStringProperty, value); }
}
public static readonly PropertyInfo<bool> IsApprovedProperty = RegisterProperty<bool>(p => p.IsApproved);
/// <summary>
/// The original membership IsApproved column
/// </summary>
/// <remarks>
/// Value comes from the aspnet_Membership tables
/// </remarks>
public bool IsApproved {
get { return GetProperty(IsApprovedProperty); }
private set { LoadProperty(IsApprovedProperty, value); }
}
public static readonly PropertyInfo<List<string>> OrgsProperty = RegisterProperty<List<string>>(p => p.Orgs);
/// <summary>
/// Returns the list of Departments that the user belongs to
/// </summary>
public List<string> Orgs {
get { return GetProperty(OrgsProperty); }
private set { LoadProperty(OrgsProperty, value); }
}
public static readonly PropertyInfo<string> AppNameProperty = RegisterProperty<string>(p => p.AppName);
public string AppName {
get { return "AppName"; }
}
#endregion
public static void GetCustomIdentity(string username, string password, EventHandler<DataPortalResult<CustomIdentity>> callback) {
DataPortal.BeginFetch<CustomIdentity>(new UsernameCriteria(username, password), callback);
}
#if !SILVERLIGHT
/// <summary>
/// Gets the user after authenticating them with their username and password
/// </summary>
/// <param name="pUserName">The user's employee number</param>
/// <param name="pPassword">The user's password</param>
/// <returns></returns>
public static CustomIdentity GetCustomIdentity(string username, string password) {
return DataPortal.Fetch<CustomIdentity>(new UsernameCriteria(username, password));
}
private void DataPortal_Fetch(UsernameCriteria criteria) {
AuthenticationType = "Custom";
using (var mgr = DataAccess.DalFactory.GetManager()) {
var dal = mgr.GetProvider<DataAccess.IIdentityDal>();
if (dal.VerifyUser(criteria.Username, criteria.Password))
LoadUserData(criteria.Username, dal);
}
}
/// <summary>
/// Gets the user based on their username
/// </summary>
/// <param name="pUserName">The user's employee number</param>
/// <returns></returns>
internal static CustomIdentity GetCustomIdentity(string username) {
return DataPortal.Fetch<CustomIdentity>(username);
}
private void DataPortal_Fetch(string username) {
AuthenticationType = "Custom";
using (var mgr = DataAccess.DalFactory.GetManager()) {
var dal = mgr.GetProvider<DataAccess.IIdentityDal>();
LoadUserData(username, dal);
}
}
/// <summary>
/// Uses the DataAccess DalFactory to dynamically load the required membership provider
/// </summary>
/// <param name="pUserName">The user's employee number</param>
/// <param name="dal">The Identity's data access object</param>
private void LoadUserData(string pUserName, DataAccess.IIdentityDal dal) {
var userData = dal.GetUser(pUserName);
//Step 1 authentication loading - If the user exists in the membership tables, the user is temporarily authenticated
this.IsAuthenticated = (userData != null);
if (this.IsAuthenticated) {
this.Name = userData.UserName;
this.FirstName = userData.FirstName;
this.LastName = userData.LastName;
this.FullName = string.Format("{0} {1}", userData.FirstName, userData.LastName);
this.Email = userData.Email;
this.UserId = userData.UserId;
this.HomeOrgString = userData.HomeOrgString;
this.IsApproved = userData.IsApproved;
//Step 2 authentication loading - Update the Identity's IsAuthenticated property based on the membership table
this.IsAuthenticated = this.IsApproved;
//Initialize the MobileList property and then load up the roles once we've gotten them
this.Roles = new Csla.Core.MobileList<string>();
string[] _roles = UserRole.GetRolesForUser(pUserName, string.Empty, true);
foreach (var role in _roles) {
this.Roles.Add(role);
}
//Load up the Orgs the user belongs to
this.Orgs = UserOrg.GetOrgsForUser(pUserName, true, false).ToList();
//Step 3 authentication loading - Check to make sure that even if the user is authenticated with AD and exists in the membership table, the user has at least 1 Org and Role
if (!(this.Orgs.Count() > 0 && this.Roles.Count() > 0)) {
this.IsAuthenticated = false;
throw new InvalidOperationException(string.Format("User {0} does not have access to any departments and/or roles.\n Org Count: {1};\n Role Count: {2}", this.Name, this.Orgs.Count(), this.Roles.Count()));
}
}
}
#endif
}
}