Skip to content

Instantly share code, notes, and snippets.

@joshrobb
Created August 25, 2010 08:43
Show Gist options
  • Save joshrobb/549124 to your computer and use it in GitHub Desktop.
Save joshrobb/549124 to your computer and use it in GitHub Desktop.
using System;
using System.Web.Mvc;
using V2.Domain.Services;
using V2.Domain.Services.Messages;
using MvcContrib.Attributes;
using System.Linq;
namespace V2.Web.Controllers
{
public class RegistrationController : ControllerBase
{
private readonly IMessageProcessor _messageProcessor;
public RegistrationController( IMessageProcessor messageProcessor )
{
_messageProcessor = messageProcessor;
}
[AcceptPost]
public ActionResult Index( RegistrationRequest request )
{
Func<ActionResult> showErrors = () => Index();
if( !ModelState.IsValid )
{
return showErrors();
}
Func<ActionResult> termsNotAccepted = () =>
{
ModelState.AddModelError( "AcceptTermsAndConditions",
"You must accept the terms and condition before registration can proceed." );
return showErrors();
};
Func<ActionResult> usernameInUse = () =>
{
ModelState.AddModelError( "Username",
"Username is in use. Please enter a different username." );
return showErrors();
};
Func<ActionResult> emailAddressInUse = () =>
{
ModelState.AddModelError( "EmailAddress",
"Email address is in use. Please enter a different email address." );
return showErrors();
};
Func<ActionResult> passphraseInvalid = () =>
{
ModelState.AddModelError( "Passphrase",
"Please enter a passphrase with at least 9 characters. Spaces are allowed but not counted." );
return showErrors();
};
Func<Guid, ActionResult> userRegistered = userId =>
RedirectToAction( "RegistrationComplete", new {id = userId} );
Func<ActionResult> result = null;
request.TermsNotAccepted = () => result = termsNotAccepted;
request.UsernameInUse = () => result = usernameInUse;
request.EmailAddressInUse = () => result = emailAddressInUse;
request.InvalidPassphrase = () => result = passphraseInvalid;
request.UserRegistered = id => result = () => userRegistered( id );
_messageProcessor.Process( request );
return result();
}
}
}
using System;
namespace V2.Domain.Services.Messages
{
public class RegistrationRequest : IRequest
{
private Action _termsNotAccepted = () => { };
private Action _usernameInUse = () => { };
private Action _emailAddressInUse = () => { };
private Action _invalidPassphrase = () => { };
private Action<Guid> _userRegistered = id => { };
public string Username { get; set; }
public string Passphrase { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public TimeZoneInfo Timezone { get; set; }
public bool AcceptTermsAndConditions { get; set; }
public Action TermsNotAccepted
{
get { return _termsNotAccepted; }
set { _termsNotAccepted = value; }
}
public Action UsernameInUse
{
get { return _usernameInUse; }
set { _usernameInUse = value; }
}
public Action EmailAddressInUse
{
get { return _emailAddressInUse; }
set { _emailAddressInUse = value; }
}
public Action InvalidPassphrase
{
get { return _invalidPassphrase; }
set { _invalidPassphrase = value; }
}
public Action<Guid> UserRegistered
{
get { return _userRegistered; }
set { _userRegistered = value; }
}
}
}
using V2.Domain.Model;
using V2.Domain.Services.Messages;
using V2.Domain.Services.Queries;
using V2.Domain.Types;
namespace V2.Domain.Services.RequestHandlers
{
public class RegistrationRequestHandler : IRequestHandler<RegistrationRequest>
{
private readonly IRepository<User> _users;
private readonly IUserByUsernameQuery _userByUsernameQuery;
private readonly IUserByEmailAddressQuery _userByEmailAddressQuery;
public RegistrationRequestHandler( IRepository<User> users, IUserByUsernameQuery userByUsernameQuery, IUserByEmailAddressQuery userByEmailAddressQuery )
{
_users = users;
_userByUsernameQuery = userByUsernameQuery;
_userByEmailAddressQuery = userByEmailAddressQuery;
}
public void Handle( RegistrationRequest request )
{
if( !request.AcceptTermsAndConditions )
{
request.TermsNotAccepted();
return;
}
if( !Passphrase.IsValid( request.Passphrase ))
{
request.InvalidPassphrase();
return;
}
var isUsernameInUse = _userByUsernameQuery.Execute( request.Username ) != null;
if( isUsernameInUse )
{
request.UsernameInUse();
return;
}
var isEmailAddressInUse = _userByEmailAddressQuery.Execute( request.EmailAddress ) != null;
if( isEmailAddressInUse )
{
request.EmailAddressInUse();
return;
}
var user = User.Register( request.Username, request.Passphrase, request.Name, request.EmailAddress, request.Timezone );
_users.Add( user );
request.UserRegistered( user.Id );
}
}
}
using System;
using System.Collections.Generic;
using V2.Domain.Events;
namespace V2.Domain.Model
{
public class User : Entity<User>
{
public static User Register( string username, string passphrase, string name, string emailAddress, TimeZoneInfo timezone )
{
var user = new User( username, passphrase, name, emailAddress, timezone );
DomainEvents.Raise( new UserRegistered( user ) );
return user;
}
}
}
using V2.Domain.Model;
namespace V2.Domain.Events
{
public class UserRegistered : IDomainEvent
{
public UserRegistered( User user )
{
User = user;
}
public User User { get; private set; }
}
}
using V2.Domain.Events;
using V2.Domain.Model;
using V2.Domain.Types;
using V2.Infrastructure.Services.Email;
using V2.ExtensionMethods;
namespace V2.Domain.Services.EventHandlers
{
public class UserRegisteredHandler : IHandles<UserRegistered>
{
private readonly IEmailService _email;
readonly IUrlConverter _urlConverter;
private readonly IRepository<LogEntry> _eventLog;
public UserRegisteredHandler( IEmailService email, IUrlConverter urlConverter, IRepository<LogEntry> eventLog )
{
_email = email;
_urlConverter = urlConverter;
_eventLog = eventLog;
}
public void Handle( UserRegistered args )
{
SendRegistrationConfirmationEmail( args.User );
LogRegistration( args.User );
}
private void SendRegistrationConfirmationEmail( User user )
{
var verificationHash = VerificationHash.Generate( user );
var registrationConfirmation = new RegistrationConfirmation
{
EmailAddress = user.EmailAddress,
Name = user.Name,
ConfirmationUrl = _urlConverter.Shorten( "/ConfirmEmailAddress/{0}/{1}".FormatWith( user.Id, verificationHash ) ),
ForgottenPassphraseUrl = _urlConverter.MakeAbsolute( "/Authentication/ForgottenPassphrase" )
};
_email.SendMessage( "RegistrationConfirmationEmail", registrationConfirmation, true );
}
private void LogRegistration( User user )
{
var registrationLogEntry = new UserRegisteredLogEntry( user, SystemTime.Now() );
_eventLog.Add( registrationLogEntry );
}
}
public class RegistrationConfirmation
{
public string EmailAddress { get; set; }
public string Name { get; set; }
public string ConfirmationUrl { get; set; }
public string ForgottenPassphraseUrl { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment