try-catch-FAIL - Fail TrackerFailure is inevitablehttp://trycatchfail.com/blog/
http://www.rssboard.org/rss-specificationBlogEngine.NET 3.1.1.0en-UShttp://trycatchfail.com/blog/opml.axdMatt Honeycutttry-catch-FAIL0.0000000.000000Source Code for “Build Your Own Application Framework” Course Online<p>If you do a quick Google for Fail Tracker, the sample project I used in my <a href="http://pluralsight.com/training/Courses/TableOfContents/build-application-framework-aspdotnet-mvc-5" target="_blank">Pluralsight course</a>, you will end up at a <a href="https://github.com/MattHoneycutt/Fail-Tracker" target="_blank">Github project page for Fail Tracker</a> that I set up back in 2011.&#160; That’s when I first used “Fail Tracker” in a demo (at CodeStock!), and until today, it has hosted only the very old, obsolete version of this application.&#160; I corrected that problem a few moments ago, so the project page now contains the same version of the application that I used in my Pluralsight course.&#160; Enjoy!</p>http://trycatchfail.com/blog/post/Source-Code-for-e2809cBuild-Your-Own-Application-Frameworke2809d-Course-Online
http://trycatchfail.com/blog/post/Source-Code-for-e2809cBuild-Your-Own-Application-Frameworke2809d-Course-Online#disqus_threadhttp://trycatchfail.com/blog/post.aspx?id=f4bcdc46-bdb7-48a8-9cbe-1fecdc0601a7Fri, 28 Mar 2014 07:45:18 -1300Fail Trackerfail-trackerpluralsightasp.net mvcMatthttp://trycatchfail.com/blog/pingback.axdhttp://trycatchfail.com/blog/post.aspx?id=f4bcdc46-bdb7-48a8-9cbe-1fecdc0601a70http://trycatchfail.com/blog/trackback.axd?id=f4bcdc46-bdb7-48a8-9cbe-1fecdc0601a7http://trycatchfail.com/blog/post/Source-Code-for-e2809cBuild-Your-Own-Application-Frameworke2809d-Course-Online#disqus_threadhttp://trycatchfail.com/blog/syndication.axd?post=f4bcdc46-bdb7-48a8-9cbe-1fecdc0601a7Data Access in Fail Tracker–Row-Level Security with LINQ to NHibernate<p>This is the third and probably final post about how data access is performed in <a href="https://github.com/MattHoneycutt/Fail-Tracker">Fail Tracker</a>.&#160; I’ve previously shown you the <a href="http://trycatchfail.com/blog/post/Data-Access-in-Fail-Tracker.aspx" target="_blank">basics of how its repository-pattern based approach</a> and how a <a href="http://trycatchfail.com/blog/post/Data-Access-in-Fail-Trackere28093Unit-Testing.aspx" target="_blank">shared base SpecsFor test fixture is leveraged to simplify testing</a>.&#160; In this post, I’ll show you how the decorator pattern is employed to provide simple, pain-free row-level security, ensuring that users can only see projects and issues that they’ve been granted access to.</p> <p></p> <h2>Why Security Matters</h2> <p>Fail Tracker is a multi-tenant application: a single instance my hold many projects for many different users.&#160; Therefore, security is quite important.&#160; I would consider it a major bug if the application disclosed project or story information to a user that shouldn’t have access to that information.&#160; Essentially every operation in Fail Tracker has a security risk to it, and enforcing this cross-cutting concern in every action would be quite painful.&#160; You would essentially have code that looks like this in every single action method:</p> <pre class="brush: csharp;">public class DashboardController : AuthorizedFailTrackerController
{
private readonly IRepository&lt;Project&gt; _projects;
private readonly IRepository&lt;User&gt; _users;
public DashboardController(IRepository&lt;Project&gt; projects, IRepository&lt;User&gt; users)
{
_projects = projects;
_users = users;
}
public ActionResult Index()
{
//Get current user, identity has the user's E-mail address
var currentUser = _users.Query().Single(u =&gt; u.EmailAddress == this.User.Identity.Name);
var projects = (from p in _projects.Query()
//Only show projects that the user is a member of
where p.Members.Contains(currentUser)
select Mapper.Map&lt;Project,ProjectDashboardViewModel&gt;(p)).ToArray();
return View(projects);
}
}</pre>
<p>While not overly complex, this is certainly not ideal.&#160; Aside from muddying up the action methods themselves, it introduces additional testing requirements and makes the code far more brittle, and it greatly increases the risk of a security problem in the application.&#160; What happens if a developer implementing a new feature forgets to limit the data coming back from a query by the current user?&#160; A better solution is needed, one that is transparent at the action method level.&#160; IMO, the ideal solution is one that is baked in to the application framework itself and that is automagically applied to all features implemented in the future.</p>
<h2>Implementing Row-Level Security Using the Decorator Pattern</h2>
<p>Security is one area where Fail Tracker’s use of the repository pattern really pays off.&#160; It is downright <strong>trivial</strong> to add row-level security without actually changing the repository layer.&#160; This is accomplished by using the <a href="http://c2.com/cgi/wiki?DecoratorPattern" target="_blank">decorator pattern</a>:</p>
<blockquote>
<p><strong>Intent:</strong> Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.</p>
</blockquote>
<p>The idea is pretty simple: by applying a security decorator to the repository via the IoC container (which, by the way, powers <strong>everything</strong> in Fail Tracker), we can control access to the repository without having to actually change the repository itself or how it’s utilized.&#160; Recall that the the repository interface and its implementation in Fail Tracker is indeed quite simple:</p>
<pre class="brush: csharp;">public interface IRepository&lt;TEntity&gt;
{
void Save(TEntity entity);
IQueryable&lt;TEntity&gt; Query();
}
public class NHibernateRepository&lt;TEntity&gt; : IRepository&lt;TEntity&gt;
{
private readonly ISession _session;
public NHibernateRepository(ISession session)
{
_session = session;
}
public void Save(TEntity entity)
{
_session.Save(entity);
_session.Flush();
}
public IQueryable&lt;TEntity&gt; Query()
{
return _session.Query&lt;TEntity&gt;();
}
}</pre>
<p>The repository implementation is generic; it’s used for both Project and Issue access.&#160; Unfortunately the steps needed to secure these two entities are slightly different.&#160; With a Project, you can simply check its members.&#160; For an Issue, you must locate its Project, then check the Project’s members.&#160; Because of this, security cannot be implemented as a generic decorator and must be specific to each type:</p>
<pre class="brush: csharp;">public class ProjectSecurityDecorator : IRepository&lt;Project&gt;
{
private readonly IRepository&lt;Project&gt; _repository;
private readonly CurrentUser _user;
public ProjectSecurityDecorator(IRepository&lt;Project&gt; repository, CurrentUser user)
{
_repository = repository;
_user = user;
}
public void Save(Project entity)
{
_repository.Save(entity);
}
public IQueryable&lt;Project&gt; Query()
{
//TODO: Eventually Fail Tracker admins should be able to see everything.
return from p in _repository.Query()
where p.Members.Contains(_user.Instance)
select p;
}
}
public class IssueSecurityDecorator : IRepository&lt;Issue&gt;
{
private readonly IRepository&lt;Issue&gt; _repository;
private readonly CurrentUser _user;
public IssueSecurityDecorator(IRepository&lt;Issue&gt; repository, CurrentUser user)
{
_repository = repository;
_user = user;
}
public void Save(Issue entity)
{
_repository.Save(entity);
}
public IQueryable&lt;Issue&gt; Query()
{
//TODO: Eventually Fail Tracker admins should be able to see everything.
return from i in _repository.Query()
where i.Project.Members.Contains(_user.Instance)
select i;
}
}</pre>
<p>With a little bit of StructureMap registry magic, all requests for either the Project or Issue repository will return decorated instances of the repository, ensuring that all data access in Fail Tracker is performed according to our security rules:</p>
<pre class="brush: csharp;">public class SecurityRegistry : Registry
{
public SecurityRegistry()
{
For&lt;CurrentUser&gt;().Add&lt;CurrentUser&gt;();
For(typeof(IRepository&lt;Project&gt;))
.EnrichWith((ctx, obj) =&gt; new ProjectSecurityDecorator((IRepository&lt;Project&gt;)obj, ctx.GetInstance&lt;CurrentUser&gt;()));
For(typeof(IRepository&lt;Issue&gt;))
.EnrichWith((ctx, obj) =&gt; new IssueSecurityDecorator((IRepository&lt;Issue&gt;)obj, ctx.GetInstance&lt;CurrentUser&gt;()));
}
}</pre>
<p>Note that <strong>nothing</strong> changes in any of our controllers.&#160; They can simply continue to consume IRepository&lt;Project&gt; or IRepository&lt;Issue&gt; as they always have.&#160; They are completely ignorant of the security concerns, which is actually a good thing. I now have row-level security everywhere in Fail Tracker without needing to think about it.&#160; This greatly simplifies new feature development and gives me much more confidence in making changes.&#160; Plus, since security is encapsulated in two decorators instead of strewn about the codebase, it will be far easier to change how security works in the future should the need arise.&#160; </p>
<h2>“What’s that CurrentUser thing??”</h2>
<p>Ahh, I almost forgot about that.&#160; CurrentUser is a lazily-evaluated way to get the actual User object corresponding to the User making the web request:</p>
<pre class="brush: csharp;">public class CurrentUser
{
private readonly IRepository&lt;User&gt; _users;
private readonly IIdentity _currentUser;
public CurrentUser(IRepository&lt;User&gt; users, IIdentity currentUser)
{
_users = users;
_currentUser = currentUser;
}
public User Instance
{
get { return _users.Query().Single(u =&gt; u.EmailAddress == _currentUser.Name); }
}
}</pre>
<p>Note that it finds the current user via IIdentity, which the Fail Tracker application framework makes available via the container.&#160; See the <a href="https://github.com/MattHoneycutt/Fail-Tracker/blob/master/FailTracker.Web/Infrastructure/MvcRegistry.cs" target="_blank">MvcRegistry</a> if you want to know more. </p>
<h2>More Than One Way to Skin a Cat</h2>
<p>There are other ways to implement this sort of security.&#160; Ayende’s <a href="https://github.com/ayende/rhino-security" target="_blank">Rhino Security</a> framework is one such solution.&#160; I considered using Rhino Security but felt that it was overly complex for what I needed, and my solution based on the repository and decorator patterns seemed sufficient.&#160; Still, my solution isn’t perfect.&#160; It bugs me that I need two decorators and can’t enforce security generically with a single decorator.&#160; If anyone has suggestions on how to get around that, please let me know!</p>http://trycatchfail.com/blog/post/Data-Access-in-Fail-Trackere28093Row-Level-Security-with-LINQ-to-NHibernate
http://trycatchfail.com/blog/post/Data-Access-in-Fail-Trackere28093Row-Level-Security-with-LINQ-to-NHibernate#disqus_threadhttp://trycatchfail.com/blog/post.aspx?id=341b5e1a-e4f4-4c54-a913-def86f55662eSat, 03 Sep 2011 03:17:24 -1300Fail TrackerNHibernateMatthttp://trycatchfail.com/blog/pingback.axdhttp://trycatchfail.com/blog/post.aspx?id=341b5e1a-e4f4-4c54-a913-def86f55662e3http://trycatchfail.com/blog/trackback.axd?id=341b5e1a-e4f4-4c54-a913-def86f55662ehttp://trycatchfail.com/blog/post/Data-Access-in-Fail-Trackere28093Row-Level-Security-with-LINQ-to-NHibernate#disqus_threadhttp://trycatchfail.com/blog/syndication.axd?post=341b5e1a-e4f4-4c54-a913-def86f55662eData Access in Fail Tracker–Unit Testing<p>In my last post, I described <a href="https://github.com/MattHoneycutt/Fail-Tracker" target="_blank">Fail Tracker</a>’s simple repository model for abstracting LINQ to <a href="http://nhforge.org/" target="_blank">NHibernate</a>, which is used for all data access in Fail Tracker.&#160; One reason I chose to implement an abstraction around NHibernate’s ISession interface was to facilitate <a href="http://en.wikipedia.org/wiki/Test-driven_development" target="_blank">Test Driven Development</a>, a practice that wasn’t really feasible given how LINQ to NHibernate is implemented as an unmockable extension method.&#160; While the abstraction made data access mockable, it would still have been painful if it weren’t for a base <a href="http://specsfor.codeplex.com/" target="_blank">SpecsFor</a> context that handled all the heavy lifting.&#160; </p> <p></p> <h2>Mocking The Hard Way</h2> <p>Recall that the IRepository interface used by Fail Tracker has only two methods:</p> <p><script src="http://gist.github.com/1161490.js"></script></p> <p>There’s not much to do when mocking Save, we typically just check to make sure that it’s called with the correct object.&#160; It’s the Query method that can be a bit of a pain.&#160; Depending on the type of repository, we might need to set up one or more projects, users, or issues.&#160; One approach is to set up custom test data for each test fixture, like so:</p> <p><script src="http://gist.github.com/1161506.js"></script></p> <p>Since Query returns IQueryable, we can setup our mock to return an IEnumerable that’s been wrapped as an IQueryable.&#160; </p> <p>While this will work on a small scale, it isn’t ideal.&#160; First, you are going to have a lot of duplicated setup code across your fixtures.&#160; Second, your test data is going to have enough variance that you won’t be able to easily remember what your test data looks like for a given test fixture.&#160; You’ll have to dig in to see what your test data actually looks like whenever you revisit a fixture in the future.&#160; Let’s look at a better approach utilizing a custom SpecsFor base class.</p> <h2>Mocking The Reusable Way</h2> <p>As mentioned, one downside to setting up mocks for each fixture individually is the repetition of code.&#160; Even if you aren’t setting up exactly the same data, the code will still be largely identical.&#160; Another downside is that the variance in test data will obfuscate the context and require that you dig in to your context anytime you need to alter a test.&#160; We can solve both of these issues by creating a custom SpecsFor base class, and establishing consistent test data that we’ll leverage in all of our test cases.&#160; Here’s the custom SpecsFor base class for Fail Tracker specs that require test data:</p> <p><script src="http://gist.github.com/1161514.js"></script></p> <p>To utilize this data, all the test fixtures need to do is inherit from this custom class instead of the default SpecsFor&lt;T&gt; class:</p> <p><script src="http://gist.github.com/1172590.js"></script></p> <p>Another nice benefit: if my domain model changes in the future, I don’t have to hunt through setup code across dozens of test fixtures.&#160; I can go straight to my custom SpecsFor base class and update my test data there, leaving my test fixtures unchanged. </p> <h2>What’s Next</h2> <p>I have one more post planned around Fail Tracker’s data access code, and it’s a doozy: row-level security.&#160; In the next post, I’ll show you how you can easily implement row level security by leveraging the decorator pattern. </p>http://trycatchfail.com/blog/post/Data-Access-in-Fail-Trackere28093Unit-Testing
http://trycatchfail.com/blog/post/Data-Access-in-Fail-Trackere28093Unit-Testing#disqus_threadhttp://trycatchfail.com/blog/post.aspx?id=ac37525a-7730-4cb2-9129-86b57ae78649Thu, 25 Aug 2011 14:15:57 -1300SpecsForTestingFail TrackerMatthttp://trycatchfail.com/blog/pingback.axdhttp://trycatchfail.com/blog/post.aspx?id=ac37525a-7730-4cb2-9129-86b57ae786490http://trycatchfail.com/blog/trackback.axd?id=ac37525a-7730-4cb2-9129-86b57ae78649http://trycatchfail.com/blog/post/Data-Access-in-Fail-Trackere28093Unit-Testing#disqus_threadhttp://trycatchfail.com/blog/syndication.axd?post=ac37525a-7730-4cb2-9129-86b57ae78649