views:

108

answers:

3

I'm writing a site in ASP.NET MVC that will have user accounts. As the site will be oriented towards discussion, I think I need a system for admins to be able to moderate users, just like we have here, on Stack Overflow. I'd like to be able to put a user into a "suspension", so that they are able to log in to the site (at which point they are greeted with a message, such as, "Your account has been suspended until [DATE]"), but are unable to do the functions that users they would normally be able to do.

What's the best way of implementing this?

I was thinking of creating a "Suspended" role, but the thing is, I have a few different roles for normal users themselves, with different privileges.

Have you ever designed a feature like this before? How should I do it? Thanks in advance.

+2  A: 

I don't know what your object model looks like, but I would assume that any user could be suspended.

Edit: I've thought of an alternate solution which is probably simpler considering that you will need to serialize the data somewhere. Perhaps you could use a regular DateTime on your 'user' object, but initialize it to DateTime.MinValue for new users. Whenever you put a user 'in suspension', set suspendedUntil to the time they are suspended until.

DateTime suspendedUntil = DateTime.MinValue;

Whenever you need to check to see whether a user is in suspension or not, just compare suspendedUntil with DateTime.Now. If suspendedUntil comes after DateTime.Now, you know the user is suspended until the date and time specified. Otherwise, the user is not suspended. After a user comes out of suspension, there is no need to modify suspendedUntil since it will then be after DateTime.Now.

bool userIsSuspended = suspendedUntil > DateTime.Now;

Serializing the DateTime would be a matter of saving the value of suspendedUntil.ToBinary() and "rehydrating" it using DateTime.FromBinary(long).

Zach Johnson
This is a very interesting solution: I'm going to try both yours and James Westgate's solution tomorrow.
Maxim Zaslavsky
+3  A: 

I think roles is the way to go without writing lots of plumbing code.

Create a role called Active which everyone is a member of by default. Then take users out of that role while they are suspended.

Every action you want to deny to suspended users requires the Active role. Simples.

James Westgate
Hold on: Users can belong to more than one role at a time, right? That way, if I have multiple user roles, all users would still be Active, and when suspended, they'd lack Active but still have their general roles.
Maxim Zaslavsky
Thats the idea yep.
James Westgate
I'll try that! Seems like a pretty straightforward plan.
Maxim Zaslavsky
+2  A: 

Let me convert a comment to an answer and rape Zach and James answers to provide what I think would be a workable solution without the need to enter the 'custom provider zone'. While writing custom providers is not terribly complicated it is my experience that if you can get the built in providers to do what you want, even if it requires a smell here or there, is always the best route.

Add a role, say WellGroomedAndBehavesSelf, that controls access to things that well groomed and behaved users should have access to.

Implement a profile in your web.config and add a ReinstateDate property (or UngroundedOnDate ;-D).

When a user misbehaves, remove them from the role WellGroomedAndBehavesSelf and set the ReinstateDate profile property.

In your login logic, override OnAuthenticate and check for a ReinstateDate profile property, if present and passed, clear it and add the user to the role WellGroomedAndBehavesSelf.

Done and no need for custom providers.

UPDATE: An alternate approach, and probably more robust preventing users from being grounded forever if somehow the profile gets cleared elsewhere than login logic, is to check for the role WellGroomedAndBehavesSelf and if missing, THEN check the profile for ReinstateDate. If it has passed or is not present, put the user back into WellGroomedAndBehavesSelf.

Same effect, but the subtle change in logic will provide a more robust solution.

How to implement Profiles:

If you are using a Web Site project look here.

If you are using a Web Application project look here.

Sky Sanders
I think I'm actually going to use this solution. Could you explain the part where you say, "Implement a profile in your web.config and add a ReinstateDate property (or UngroundedOnDate ;-D)"? I'm not really sure how to add a property to the profile in web.config. Thanks!
Maxim Zaslavsky
@maxim - updated answer.
Sky Sanders
Thank you! I'm kind of new to ASP.NET MVC: where do I create the role? Also, how can I configure the Profile into a SQL Server table?
Maxim Zaslavsky
@maxim - you should start by reading the documents linked above to get a background on how the profile system works, then you can focus on MVC by reading the answers here http://stackoverflow.com/questions/79129/implementing-profile-provider-in-asp-net-mvc , http://stackoverflow.com/questions/834166/implementing-custom-profile-provider-in-asp-net-mvc, http://joyofexcellence.com/blog/index.php/2009/05/17/profileprovider-in-an-mvc-world/, OR http://tinyurl.com/2fd63qv ;-p
Sky Sanders