mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Building out user services
--HG-- extra : convert_revision : svn%3A5ff7c347-ad56-4c35-b696-ccb81de16e03/trunk%4039351
This commit is contained in:
@@ -31,10 +31,39 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Autofac, Version=1.4.4.561, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\autofac\Autofac.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="FluentNHibernate, Version=1.0.0.593, Culture=neutral, PublicKeyToken=8aa435e3cb308880, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\fluentnhibernate\FluentNHibernate.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NHibernate, Version=2.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\fluentnhibernate\NHibernate.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NHibernate.ByteCode.Castle, Version=2.1.0.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\fluentnhibernate\NHibernate.ByteCode.Castle.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="nunit.framework, Version=2.5.2.9222, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\nunit\nunit.framework.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SQLite, Version=1.0.65.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\sqlite\System.Data.SQLite.DLL</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
@@ -46,9 +75,21 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Users\Services\MembershipServiceTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Users\" />
|
||||
<ProjectReference Include="..\Orchard.Tests\Orchard.Tests.csproj">
|
||||
<Project>{ABC826D4-2FA1-4F2F-87DE-E6095F653810}</Project>
|
||||
<Name>Orchard.Tests</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.Web\Packages\Orchard.Users\Orchard.Users.csproj">
|
||||
<Project>{79AED36E-ABD0-4747-93D3-8722B042454B}</Project>
|
||||
<Name>Orchard.Users</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard\Orchard.csproj">
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Name>Orchard</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
@@ -0,0 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Autofac.Builder;
|
||||
using Autofac.Modules;
|
||||
using NHibernate;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Data;
|
||||
using Orchard.Models;
|
||||
using Orchard.Models.Driver;
|
||||
using Orchard.Models.Records;
|
||||
using Orchard.Security;
|
||||
using Orchard.Users.Models;
|
||||
using Orchard.Users.Services;
|
||||
|
||||
namespace Orchard.Tests.Packages.Users.Services {
|
||||
[TestFixture]
|
||||
public class MembershipServiceTests {
|
||||
private IMembershipService _membershipService;
|
||||
private ISessionFactory _sessionFactory;
|
||||
private ISession _session;
|
||||
|
||||
|
||||
public class TestSessionLocator : ISessionLocator {
|
||||
private readonly ISession _session;
|
||||
|
||||
public TestSessionLocator(ISession session) {
|
||||
_session = session;
|
||||
}
|
||||
|
||||
public ISession For(Type entityType) {
|
||||
return _session;
|
||||
}
|
||||
}
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void InitFixture() {
|
||||
var databaseFileName = System.IO.Path.GetTempFileName();
|
||||
_sessionFactory = DataUtility.CreateSessionFactory(
|
||||
databaseFileName,
|
||||
typeof(ModelRecord),
|
||||
typeof(ModelTypeRecord));
|
||||
}
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void TermFixture() {
|
||||
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.RegisterModule(new ImplicitCollectionSupportModule());
|
||||
builder.Register<MembershipService>().As<IMembershipService>();
|
||||
builder.Register<DefaultModelManager>().As<IModelManager>();
|
||||
builder.Register<UserDriver>().As<IModelDriver>();
|
||||
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
|
||||
_session = _sessionFactory.OpenSession();
|
||||
builder.Register(new TestSessionLocator(_session)).As<ISessionLocator>();
|
||||
var container = builder.Build();
|
||||
_membershipService = container.Resolve<IMembershipService>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateUserShouldAllocateModelAndCreateRecords() {
|
||||
var user = _membershipService.CreateUser(new CreateUserParams("a", "b", "c", null, null, true));
|
||||
Assert.That(user.UserName, Is.EqualTo("a"));
|
||||
Assert.That(user.Email, Is.EqualTo("c"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -136,6 +136,15 @@ namespace Orchard.Tests.Models {
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateShouldMakeModelAndModelTypeRecords() {
|
||||
var beta = _manager.New("beta");
|
||||
_manager.Create(beta);
|
||||
|
||||
var modelRecord = _container.Resolve<IRepository<ModelRecord>>().Get(beta.Id);
|
||||
Assert.That(modelRecord, Is.Not.Null);
|
||||
Assert.That(modelRecord.ModelType.Name, Is.EqualTo("beta"));
|
||||
}
|
||||
|
||||
private ModelRecord CreateModelRecord(string modelType) {
|
||||
var modelRepository = _container.Resolve<IRepository<ModelRecord>>();
|
||||
|
@@ -21,7 +21,7 @@ namespace Orchard.Tests.Mvc {
|
||||
public void Init() {
|
||||
var builder = new ContainerBuilder();
|
||||
builder.Register<ReplacementFooController>().As<IController>()
|
||||
.Named("controller.orchard.web.foo")
|
||||
.Named("controller.orchard.foo")
|
||||
.FactoryScoped();
|
||||
|
||||
var container = builder.Build();
|
||||
|
11
src/Orchard.Web/Packages/Orchard.Users/Models/UserDriver.cs
Normal file
11
src/Orchard.Web/Packages/Orchard.Users/Models/UserDriver.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using Orchard.Models.Driver;
|
||||
|
||||
namespace Orchard.Users.Models {
|
||||
public class UserDriver : ModelDriver {
|
||||
protected override void New(NewModelContext context) {
|
||||
if (context.ModelType == "user") {
|
||||
WeldModelPart<UserModel>(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
src/Orchard.Web/Packages/Orchard.Users/Models/UserModel.cs
Normal file
14
src/Orchard.Web/Packages/Orchard.Users/Models/UserModel.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.Models;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.Users.Models {
|
||||
public class UserModel : ModelPart, IUser {
|
||||
public string UserName { get; set; }
|
||||
|
||||
public string Email { get; set; }
|
||||
}
|
||||
}
|
@@ -63,17 +63,25 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Controllers\AdminController.cs" />
|
||||
<Compile Include="Controllers\HomeController.cs" />
|
||||
<Compile Include="Models\UserModel.cs" />
|
||||
<Compile Include="Models\UserDriver.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Services\MembershipService.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Package.txt" />
|
||||
<Content Include="Web.config" />
|
||||
<Content Include="Views\Web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Orchard\Orchard.csproj">
|
||||
<Project>{2D1D92BB-4555-4CBE-8D0E-63563D6CE4C6}</Project>
|
||||
<Name>Orchard</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="App_Data\" />
|
||||
<Folder Include="Content\" />
|
||||
<Folder Include="Models\" />
|
||||
<Folder Include="Scripts\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
|
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Orchard.Models;
|
||||
using Orchard.Security;
|
||||
using Orchard.Users.Models;
|
||||
|
||||
namespace Orchard.Users.Services {
|
||||
public class MembershipService : IMembershipService {
|
||||
private readonly IModelManager _modelManager;
|
||||
|
||||
public MembershipService(IModelManager modelManager) {
|
||||
_modelManager = modelManager;
|
||||
}
|
||||
|
||||
public void ReadSettings(MembershipSettings settings) {
|
||||
// accepting defaults
|
||||
}
|
||||
|
||||
public IUser CreateUser(CreateUserParams createUserParams) {
|
||||
var user = _modelManager.New("user").As<UserModel>();
|
||||
user.UserName = createUserParams.Username;
|
||||
user.Email = createUserParams.Email;
|
||||
_modelManager.Create(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
public IUser GetUser(string username) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@@ -17,14 +17,14 @@ namespace Orchard.Controllers {
|
||||
// This constructor is not used by the MVC framework but is instead provided for ease
|
||||
// of unit testing this type. See the comments at the end of this file for more
|
||||
// information.
|
||||
public AccountController(IFormsAuthentication formsAuth, IMembershipService service) {
|
||||
public AccountController(IFormsAuthentication formsAuth, IMembershipServiceShim service) {
|
||||
FormsAuth = formsAuth ?? new FormsAuthenticationService();
|
||||
MembershipService = service ?? new AccountMembershipService();
|
||||
}
|
||||
|
||||
public IFormsAuthentication FormsAuth { get; private set; }
|
||||
|
||||
public IMembershipService MembershipService { get; private set; }
|
||||
public IMembershipServiceShim MembershipService { get; private set; }
|
||||
|
||||
public ActionResult LogOn() {
|
||||
return View();
|
||||
@@ -238,7 +238,7 @@ namespace Orchard.Controllers {
|
||||
#endregion
|
||||
}
|
||||
|
||||
public interface IMembershipService {
|
||||
public interface IMembershipServiceShim {
|
||||
int MinPasswordLength { get; }
|
||||
|
||||
bool ValidateUser(string userName, string password);
|
||||
@@ -246,7 +246,7 @@ namespace Orchard.Controllers {
|
||||
bool ChangePassword(string userName, string oldPassword, string newPassword);
|
||||
}
|
||||
|
||||
public class AccountMembershipService : IMembershipService {
|
||||
public class AccountMembershipService : IMembershipServiceShim {
|
||||
private readonly MembershipProvider _provider;
|
||||
|
||||
public AccountMembershipService()
|
||||
|
@@ -8,12 +8,15 @@ namespace Orchard.Models {
|
||||
public class DefaultModelManager : IModelManager {
|
||||
private readonly IEnumerable<IModelDriver> _drivers;
|
||||
private readonly IRepository<ModelRecord> _modelRepository;
|
||||
private readonly IRepository<ModelTypeRecord> _modelTypeRepository;
|
||||
|
||||
public DefaultModelManager(
|
||||
IEnumerable<IModelDriver> drivers,
|
||||
IRepository<ModelRecord> modelRepository) {
|
||||
IRepository<ModelRecord> modelRepository,
|
||||
IRepository<ModelTypeRecord> modelTypeRepository) {
|
||||
_drivers = drivers;
|
||||
_modelRepository = modelRepository;
|
||||
_modelTypeRepository = modelTypeRepository;
|
||||
}
|
||||
|
||||
public virtual IModel New(string modelType) {
|
||||
@@ -47,12 +50,44 @@ namespace Orchard.Models {
|
||||
// set the id
|
||||
context.Instance.As<ModelRoot>().Id = context.Id;
|
||||
|
||||
// invoke drivers to weld aspects onto kernel
|
||||
// invoke drivers to acquire state, or at least establish lazy loading callbacks
|
||||
foreach (var driver in _drivers) {
|
||||
driver.Load(context);
|
||||
}
|
||||
|
||||
return context.Instance;
|
||||
}
|
||||
|
||||
public void Create(IModel model) {
|
||||
// produce root record to determine the model id
|
||||
var modelRecord = new ModelRecord {ModelType = AcquireModelTypeRecord(model.ModelType)};
|
||||
_modelRepository.Create(modelRecord);
|
||||
|
||||
// build a context with the initialized instance to create
|
||||
var context = new CreateModelContext {
|
||||
Id = modelRecord.Id,
|
||||
ModelType = modelRecord.ModelType.Name,
|
||||
Instance = model.As<ModelRoot>().Welded
|
||||
};
|
||||
|
||||
// set the id
|
||||
context.Instance.As<ModelRoot>().Id = context.Id;
|
||||
|
||||
|
||||
// invoke drivers to add information to persistent stores
|
||||
foreach (var driver in _drivers) {
|
||||
driver.Create(context);
|
||||
}
|
||||
}
|
||||
|
||||
private ModelTypeRecord AcquireModelTypeRecord(string modelType) {
|
||||
var modelTypeRecord = _modelTypeRepository.Get(x => x.Name == modelType);
|
||||
if (modelTypeRecord == null) {
|
||||
//TEMP: this is not safe... Model types could be created concurrently?
|
||||
modelTypeRecord = new ModelTypeRecord {Name = modelType};
|
||||
_modelTypeRepository.Create(modelTypeRecord);
|
||||
}
|
||||
return modelTypeRecord;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
namespace Orchard.Models.Driver {
|
||||
public interface IModelDriver : IDependency {
|
||||
void New(NewModelContext context);
|
||||
void Create(CreateModelContext context);
|
||||
void Load(LoadModelContext context);
|
||||
}
|
||||
}
|
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Orchard.Data;
|
||||
using Orchard.Logging;
|
||||
|
||||
@@ -10,6 +11,7 @@ namespace Orchard.Models.Driver {
|
||||
public ILogger Logger{ get; set;}
|
||||
|
||||
void IModelDriver.New(NewModelContext context) {New(context);}
|
||||
void IModelDriver.Create(CreateModelContext context) { Create(context); }
|
||||
void IModelDriver.Load(LoadModelContext context) { Load(context); }
|
||||
|
||||
protected virtual void New(NewModelContext context) {
|
||||
@@ -18,6 +20,9 @@ namespace Orchard.Models.Driver {
|
||||
protected virtual void Load(LoadModelContext context) {
|
||||
}
|
||||
|
||||
protected virtual void Create(CreateModelContext context) {
|
||||
}
|
||||
|
||||
protected void WeldModelPart<TPart>(NewModelContext context) where TPart : class,IModel,new() {
|
||||
var newPart = new TPart();
|
||||
newPart.Weld(context.Instance);
|
||||
|
@@ -8,4 +8,9 @@ namespace Orchard.Models.Driver {
|
||||
public string ModelType { get; set; }
|
||||
public IModel Instance { get; set; }
|
||||
}
|
||||
public class CreateModelContext {
|
||||
public int Id { get; set; }
|
||||
public string ModelType { get; set; }
|
||||
public IModel Instance { get; set; }
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,9 @@
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.Models {
|
||||
public interface IModelManager {
|
||||
IModel New(string modelType);
|
||||
IModel Get(int id);
|
||||
void Create(IModel model);
|
||||
}
|
||||
}
|
||||
|
@@ -161,6 +161,7 @@
|
||||
<Compile Include="Packages\PackageFolders.cs" />
|
||||
<Compile Include="Packages\PackageDescriptor.cs" />
|
||||
<Compile Include="Packages\PackageManager.cs" />
|
||||
<Compile Include="Security\CreateUserParams.cs" />
|
||||
<Compile Include="Security\IAuthorizationService.cs" />
|
||||
<Compile Include="Security\IMembershipService.cs" />
|
||||
<Compile Include="Security\IUser.cs" />
|
||||
|
43
src/Orchard/Security/CreateUserParams.cs
Normal file
43
src/Orchard/Security/CreateUserParams.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
namespace Orchard.Security {
|
||||
public class CreateUserParams {
|
||||
private readonly string _username;
|
||||
private readonly string _password;
|
||||
private readonly string _email;
|
||||
private readonly string _passwordQuestion;
|
||||
private readonly string _passwordAnswer;
|
||||
private readonly bool _isApproved;
|
||||
|
||||
public CreateUserParams(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved) {
|
||||
_username = username;
|
||||
_password = password;
|
||||
_email = email;
|
||||
_passwordQuestion = passwordQuestion;
|
||||
_passwordAnswer = passwordAnswer;
|
||||
_isApproved = isApproved;
|
||||
}
|
||||
|
||||
public string Username {
|
||||
get { return _username; }
|
||||
}
|
||||
|
||||
public string Password {
|
||||
get { return _password; }
|
||||
}
|
||||
|
||||
public string Email {
|
||||
get { return _email; }
|
||||
}
|
||||
|
||||
public string PasswordQuestion {
|
||||
get { return _passwordQuestion; }
|
||||
}
|
||||
|
||||
public string PasswordAnswer {
|
||||
get { return _passwordAnswer; }
|
||||
}
|
||||
|
||||
public bool IsApproved {
|
||||
get { return _isApproved; }
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,6 +7,9 @@ using System.Web.Security;
|
||||
namespace Orchard.Security {
|
||||
public interface IMembershipService : IDependency {
|
||||
void ReadSettings(MembershipSettings settings);
|
||||
|
||||
IUser CreateUser(CreateUserParams createUserParams);
|
||||
IUser GetUser(string username);
|
||||
}
|
||||
|
||||
public class MembershipSettings {
|
||||
|
@@ -8,9 +8,6 @@ using Orchard.Environment;
|
||||
|
||||
namespace Orchard.Security.Providers {
|
||||
public class OrchardMembershipProvider : MembershipProvider {
|
||||
public OrchardMembershipProvider() {
|
||||
int x =5;
|
||||
}
|
||||
|
||||
static IMembershipService GetService() {
|
||||
return ServiceLocator.Resolve<IMembershipService>();
|
||||
@@ -33,11 +30,35 @@ namespace Orchard.Security.Providers {
|
||||
return settings;
|
||||
}
|
||||
|
||||
private MembershipUser BuildMembershipUser(IUser user) {
|
||||
return new MembershipUser(Name,
|
||||
user.UserName,
|
||||
user.Id,
|
||||
user.Email,
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
false,
|
||||
DateTime.UtcNow,
|
||||
DateTime.UtcNow,
|
||||
DateTime.UtcNow,
|
||||
DateTime.UtcNow,
|
||||
DateTime.UtcNow);
|
||||
}
|
||||
|
||||
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) {
|
||||
throw new NotImplementedException();
|
||||
var user = GetService().CreateUser(new CreateUserParams(username, password, email, passwordQuestion, passwordAnswer, isApproved));
|
||||
|
||||
if (user == null) {
|
||||
status = MembershipCreateStatus.ProviderError;
|
||||
return null;
|
||||
}
|
||||
|
||||
status = MembershipCreateStatus.Success;
|
||||
return BuildMembershipUser(user);
|
||||
}
|
||||
|
||||
|
||||
public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
Reference in New Issue
Block a user