jitesh.patil wrote:
Hi,
I would like to know the design of using the IPrincipal and IIdentity with NHibernate persistent objects.
Here's mine... keep in mind, it would be adaptable if you wanted IPrincipal and IIdentity separated, I just happen to be a fan of keeping them together. Also, this is 1.2 but would easily support 1.0.2 and, of course, I have my specific mappings in here as well.
Account.hbm.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="MobysThinkTank.mobyProject.Account, mobyProject" table="Account" lazy="false">
<id name="Id" type="Int32" unsaved-value="0" access="nosetter.camelcase">
<column name="accountId" not-null="true" unique="true" />
<generator class="identity" />
</id>
<version name="Revision" column="Revision" unsaved-value="0" access="nosetter.camelcase"/>
<property name="Username" column="Username"/>
<property name="Password" column="Password"/>
<property name="EmailAddress" column="EmailAddress"/>
<property name="CurrentLoginTime" column="CurrentLoginDate"/>
<property name="LastLoginTime" column="LastLoginDate"/>
<bag name="Roles" lazy="true" cascade="all-delete-orphan" generic="true" table="AccountRoles">
<key column="accountId"></key>
<many-to-many class="MobysThinkTank.mobyProject.Role, mobyProject" column="roleId"></many-to-many>
</bag>
<bag name="ReportedIssues" lazy="true" generic="true" inverse="true">
<key column="reportedById"></key>
<one-to-many class="MobysThinkTank.mobyProject.Issue, mobyProject"/>
</bag>
<bag name="AssignedIssues" lazy="true" generic="true" inverse="true">
<key column="assignedToId"></key>
<one-to-many class="MobysThinkTank.mobyProject.Issue, mobyProject"/>
</bag>
<one-to-one name="Profile" class="MobysThinkTank.mobyProject.Profile, mobyProject" cascade="all-delete-orphan" />
</class>
</hibernate-mapping>
Role.hbm.xml
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0">
<class name="MobysThinkTank.mobyProject.Role, mobyProject" table="Role" lazy="false">
<!--<cache usage="nonstrict-read-write"/>-->
<id name="Id" type="Int32" unsaved-value="0" access="nosetter.camelcase">
<column name="roleId" not-null="true" unique="true" />
<generator class="identity" />
</id>
<version name="Revision" column="Revision" unsaved-value="0" access="nosetter.camelcase"/>
<property name="Name" column="Name"/>
</class>
</hibernate-mapping>
Account.cs
Code:
using System;
using System.Collections.Generic;
using System.Security.Principal;
using NHibernate;
namespace MobysThinkTank.mobyProject
{
public class Account : IPrincipal, IIdentity
{
protected int id;
protected string username;
protected string password;
protected string emailAddress;
protected DateTime? currentLoginTime;
protected DateTime? lastLoginTime;
protected Profile profile;
protected IList<Role> roles;
protected IList<Issue> reportedIssues;
protected IList<Issue> assignedIssues;
protected int revision;
public int Id
{
get { return id; }
}
public string Username
{
get { return username; }
set { username = value; }
}
public string Password
{
get { return password; }
set { password = value; }
}
public string EmailAddress
{
get { return emailAddress; }
set { emailAddress = value; }
}
public DateTime? CurrentLoginTime
{
get { return currentLoginTime; }
set { currentLoginTime = value; }
}
public DateTime? LastLoginTime
{
get { return lastLoginTime; }
set { lastLoginTime = value; }
}
public int Revision
{
get { return revision; }
}
public Profile Profile
{
get { return profile; }
set { profile = value; }
}
public virtual IList<Role> Roles
{
get
{
if (roles == null)
roles = new List<Role>();
return roles;
}
set
{
roles = value;
}
}
public virtual IList<Issue> ReportedIssues
{
get
{
if (reportedIssues == null)
reportedIssues = new List<Issue>();
return reportedIssues;
}
set
{
reportedIssues = value;
}
}
public virtual IList<Issue> AssignedIssues
{
get
{
if (assignedIssues == null)
assignedIssues = new List<Issue>();
return assignedIssues;
}
set
{
assignedIssues = value;
}
}
public void Save()
{
DbSessionContext.Current.Save(this);
}
public void Delete()
{
DbSessionContext.Current.Delete(this);
}
public static Account Get(int id)
{
return DbSessionContext.Current.Get<Account>(id);
}
public static Account GetByLogin(string username, string password)
{
string sql = "from Account where Username = :username and Password = :password";
IQuery query = DbSessionContext.Current.Session.CreateQuery(sql);
query.SetString("username", username);
query.SetString("password", password);
IList<Account> accountList = query.List<Account>();
if (accountList.Count == 0)
throw new AccountNotFoundException();
if (accountList.Count > 1)
throw new TooManyAccountsFoundException();
return accountList[0];
}
public static Account GetByUsername(string username)
{
string sql = "from Account where Username = :username";
IQuery query = DbSessionContext.Current.Session.CreateQuery(sql);
query.SetString("username", username);
IList<Account> accounts = query.List<Account>();
if (accounts.Count > 0)
return accounts[0];
return null;
}
public static IList<Account> Find(string username)
{
string sql = "from Account where Username like :username";
IQuery query = DbSessionContext.Current.Session.CreateQuery(sql);
query.SetString("username", username + '%');
return query.List<Account>();
}
public static IList<Account> List()
{
return DbSessionContext.Current.List<Account>();
}
#region IPrincipal Members
public IIdentity Identity
{
get { return this; }
}
public bool IsInRole(string role)
{
throw new Exception("The method or operation is not implemented.");
}
#endregion
#region IIdentity Members
public string AuthenticationType
{
get { return "mobyProject Authentication"; }
}
public bool IsAuthenticated
{
get { return true; }
}
public string Name
{
get { return username; }
}
#endregion
}
}
Role.cs
Code:
using System.Collections.Generic;
using NHibernate;
namespace MobysThinkTank.mobyProject
{
public class Role
{
protected int id;
protected string name;
protected int revision;
public int Id
{
get { return id; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public int Revision
{
get { return revision; }
}
public void Save()
{
DbSessionContext.Current.Save(this);
}
public void Delete()
{
DbSessionContext.Current.Delete(this);
}
public static Role Get(int id)
{
return DbSessionContext.Current.Get<Role>(id);
}
public static Role GetByName(string role)
{
string sql = "from Role where Name = :name";
IQuery query = DbSessionContext.Current.Session.CreateQuery(sql);
query.SetString("name", role);
IList<Role> roles = query.List<Role>();
if (roles.Count > 0)
return roles[0];
return null;
}
public static IList<Role> List()
{
return DbSessionContext.Current.List<Role>();
}
}
}
Hopefully that helps a bit...
Oh, and the AuthenticationModule.cs
Code:
private void context_AuthenticateRequest(object sender, EventArgs e)
{
if (HttpContext.Current.User != null && HttpContext.Current.User.Identity.IsAuthenticated && HttpContext.Current.User.Identity is FormsIdentity)
SecurityContext.Current.RestoreFromCookie();
}
And SecurityContext.Current.RestoreFromCookie:
Code:
public void RestoreFromCookie()
{
FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
int accountId;
int.TryParse(ticket.UserData, out accountId);
if (accountId > 0)
{
Account account = Account.Get(accountId);
Current.User = account;
}
}