* tests for user provider
* username is no longer required * added ip address property to user
This commit is contained in:
parent
7e042d3b93
commit
9a1f0347c0
@ -1,7 +1,14 @@
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
namespace VideoGameQuotes.Api {
|
namespace VideoGameQuotes.Api {
|
||||||
|
/// <summary>
|
||||||
|
/// Provides an interface for identifying the current user
|
||||||
|
/// </summary>
|
||||||
public interface ICurrentUserProvider {
|
public interface ICurrentUserProvider {
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the user currently performing actions on the site, or <c>null</c>
|
||||||
|
/// if the user cannot be identified
|
||||||
|
/// </summary>
|
||||||
[CanBeNull]
|
[CanBeNull]
|
||||||
User CurrentUser { get; }
|
User CurrentUser { get; }
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,8 @@
|
|||||||
<generator class="identity" />
|
<generator class="identity" />
|
||||||
</id>
|
</id>
|
||||||
|
|
||||||
<property name="Username" column="username" not-null="true" type="string" length="50" unique="true"/>
|
<property name="Username" column="username" not-null="false" type="string" length="50"/>
|
||||||
|
<property name="IpAddress" column="ip_address" not-null="false" type="string" length="40"/>
|
||||||
<property name="Created" column="created" not-null="true" type="DateTime" />
|
<property name="Created" column="created" not-null="true" type="DateTime" />
|
||||||
<property name="Group" column="user_group" not-null="true" />
|
<property name="Group" column="user_group" not-null="true" />
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</id>
|
</id>
|
||||||
|
|
||||||
<property name="Created" column="created" not-null="true" />
|
<property name="Created" column="created" not-null="true" />
|
||||||
<property name="Value" column="point_value" not-null="true" />
|
<property name="Direction" column="direction" not-null="true" type="int" length="1" />
|
||||||
|
|
||||||
<many-to-one name="Voter" column="voter_id" not-null="true" foreign-key="fk_vote_user"/>
|
<many-to-one name="Voter" column="voter_id" not-null="true" foreign-key="fk_vote_user"/>
|
||||||
<many-to-one name="Quote" column="quote_id" not-null="true" foreign-key="fk_vote_quote" />
|
<many-to-one name="Quote" column="quote_id" not-null="true" foreign-key="fk_vote_quote" />
|
||||||
|
@ -1,11 +1,17 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using NHibernate;
|
using NHibernate;
|
||||||
using Portoa.NHibernate;
|
using Portoa.NHibernate;
|
||||||
using Portoa.Persistence;
|
using Portoa.Persistence;
|
||||||
|
|
||||||
namespace VideoGameQuotes.Api.Persistence {
|
namespace VideoGameQuotes.Api.Persistence {
|
||||||
public interface IUserRepository : IRepository<User> {
|
public interface IUserRepository : IRepository<User> {
|
||||||
|
[CanBeNull]
|
||||||
User FindByUsername(string name);
|
User FindByUsername(string name);
|
||||||
|
|
||||||
|
[CanBeNull]
|
||||||
|
User FindByIpAddress(string ipAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UserRepository : NHibernateRepository<User>, IUserRepository {
|
public class UserRepository : NHibernateRepository<User>, IUserRepository {
|
||||||
@ -14,5 +20,9 @@ namespace VideoGameQuotes.Api.Persistence {
|
|||||||
public User FindByUsername(string name) {
|
public User FindByUsername(string name) {
|
||||||
return Records.FirstOrDefault(user => user.Username == name);
|
return Records.FirstOrDefault(user => user.Username == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public User FindByIpAddress(string ipAddress) {
|
||||||
|
return Records.FirstOrDefault(user => user.IpAddress == ipAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,10 +1,12 @@
|
|||||||
using Portoa.Persistence;
|
using System;
|
||||||
|
using Portoa.Persistence;
|
||||||
|
|
||||||
namespace VideoGameQuotes.Api.Persistence {
|
namespace VideoGameQuotes.Api.Persistence {
|
||||||
|
|
||||||
public interface IUserService {
|
public interface IUserService {
|
||||||
User Save(User user);
|
User Save(User user);
|
||||||
User FindByUsername(string name);
|
User FindByUsername(string name);
|
||||||
|
User FindByIpAddress(string ipAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UserService : IUserService {
|
public class UserService : IUserService {
|
||||||
@ -23,5 +25,10 @@ namespace VideoGameQuotes.Api.Persistence {
|
|||||||
public User FindByUsername(string name) {
|
public User FindByUsername(string name) {
|
||||||
return repository.FindByUsername(name);
|
return repository.FindByUsername(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[UnitOfWork]
|
||||||
|
public User FindByIpAddress(string ipAddress) {
|
||||||
|
return repository.FindByIpAddress(ipAddress);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ namespace VideoGameQuotes.Api {
|
|||||||
|
|
||||||
public virtual DateTime Created { get; set; }
|
public virtual DateTime Created { get; set; }
|
||||||
public virtual string Username { get; set; }
|
public virtual string Username { get; set; }
|
||||||
|
public virtual string IpAddress { get; set; }
|
||||||
public virtual UserGroup Group { get; set; }
|
public virtual UserGroup Group { get; set; }
|
||||||
|
|
||||||
public virtual void ChangePassword([DoNotLog]string newPassword) {
|
public virtual void ChangePassword([DoNotLog]string newPassword) {
|
||||||
|
@ -18,7 +18,7 @@ namespace VideoGameQuotes.Web {
|
|||||||
|
|
||||||
Container
|
Container
|
||||||
.AddNewExtension<LogAllMethodCalls>()
|
.AddNewExtension<LogAllMethodCalls>()
|
||||||
.RegisterType<ICurrentUserProvider, UserProvider>()
|
.RegisterType<ICurrentUserProvider, SessionBasedUserProvider>()
|
||||||
.RegisterType<IUserService, UserService>()
|
.RegisterType<IUserService, UserService>()
|
||||||
.RegisterType<IUserRepository, UserRepository>();
|
.RegisterType<IUserRepository, UserRepository>();
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,12 @@ using VideoGameQuotes.Api;
|
|||||||
using VideoGameQuotes.Api.Persistence;
|
using VideoGameQuotes.Api.Persistence;
|
||||||
|
|
||||||
namespace VideoGameQuotes.Web.Security {
|
namespace VideoGameQuotes.Web.Security {
|
||||||
public class UserProvider : ICurrentUserProvider {
|
public class SessionBasedUserProvider : ICurrentUserProvider {
|
||||||
private readonly IUserService userService;
|
private readonly IUserService userService;
|
||||||
private readonly ISessionStore sessionStore;
|
private readonly ISessionStore sessionStore;
|
||||||
private readonly HttpContextBase httpContext;
|
private readonly HttpContextBase httpContext;
|
||||||
|
|
||||||
public UserProvider(IUserService userService, ISessionStore sessionStore, HttpContextBase httpContext) {
|
public SessionBasedUserProvider(IUserService userService, ISessionStore sessionStore, HttpContextBase httpContext) {
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.sessionStore = sessionStore;
|
this.sessionStore = sessionStore;
|
||||||
this.httpContext = httpContext;
|
this.httpContext = httpContext;
|
||||||
@ -21,15 +21,15 @@ namespace VideoGameQuotes.Web.Security {
|
|||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
//identify user by IP address
|
//identify user by IP address
|
||||||
var username = httpContext.Request.UserHostAddress;
|
var ipAddress = httpContext.Request.UserHostAddress;
|
||||||
if (string.IsNullOrEmpty(username)) {
|
if (string.IsNullOrEmpty(ipAddress)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
user = userService.FindByUsername(username);
|
user = userService.FindByIpAddress(ipAddress);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
user = new User {
|
user = new User {
|
||||||
Username = username,
|
IpAddress = ipAddress,
|
||||||
Group = UserGroup.User
|
Group = UserGroup.User
|
||||||
};
|
};
|
||||||
|
|
@ -86,7 +86,7 @@
|
|||||||
<DependentUpon>Default.aspx</DependentUpon>
|
<DependentUpon>Default.aspx</DependentUpon>
|
||||||
<SubType>ASPXCodeBehind</SubType>
|
<SubType>ASPXCodeBehind</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Security\UserProvider.cs" />
|
<Compile Include="Security\SessionBasedUserProvider.cs" />
|
||||||
<Compile Include="Global.asax.cs">
|
<Compile Include="Global.asax.cs">
|
||||||
<DependentUpon>Global.asax</DependentUpon>
|
<DependentUpon>Global.asax</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -34,6 +34,9 @@
|
|||||||
<Reference Include="log4net">
|
<Reference Include="log4net">
|
||||||
<HintPath>..\..\Lib\log4net.dll</HintPath>
|
<HintPath>..\..\Lib\log4net.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="Moq">
|
||||||
|
<HintPath>..\..\Lib\Moq.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="MySql.Data">
|
<Reference Include="MySql.Data">
|
||||||
<HintPath>..\..\Lib\MySql.Data.dll</HintPath>
|
<HintPath>..\..\Lib\MySql.Data.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
36
Tests/VideoGameQuotes.Web.Tests/Properties/AssemblyInfo.cs
Normal file
36
Tests/VideoGameQuotes.Web.Tests/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("VideoGameQuotes.Web.Tests")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("Microsoft")]
|
||||||
|
[assembly: AssemblyProduct("VideoGameQuotes.Web.Tests")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © Microsoft 2011")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("2e52aa26-c170-44ad-801f-3ee9d6aa3fcd")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
48
Tests/VideoGameQuotes.Web.Tests/UserProviderTests.cs
Normal file
48
Tests/VideoGameQuotes.Web.Tests/UserProviderTests.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System.Web;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Portoa.Web.Session;
|
||||||
|
using VideoGameQuotes.Api;
|
||||||
|
using VideoGameQuotes.Api.Persistence;
|
||||||
|
using VideoGameQuotes.Web.Security;
|
||||||
|
|
||||||
|
namespace VideoGameQuotes.Web.Tests {
|
||||||
|
[TestFixture]
|
||||||
|
public class UserProviderTests {
|
||||||
|
[Test]
|
||||||
|
public void Should_use_user_in_session_store() {
|
||||||
|
var session = new Mock<ISessionStore>();
|
||||||
|
var user = new User();
|
||||||
|
session.SetupGet(s => s["user"]).Returns(user).Verifiable();
|
||||||
|
|
||||||
|
var userProvider = new SessionBasedUserProvider(new Mock<IUserService>().Object, session.Object, new Mock<HttpContextBase>().Object);
|
||||||
|
|
||||||
|
Assert.That(userProvider.CurrentUser, Is.EqualTo(user));
|
||||||
|
session.VerifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Should_identify_user_using_ip_address() {
|
||||||
|
var session = new Mock<ISessionStore>();
|
||||||
|
session.SetupGet(s => s["user"]).Returns(null);
|
||||||
|
|
||||||
|
var httpContext = new Mock<HttpContextBase>();
|
||||||
|
var httpRequest = new Mock<HttpRequestBase>();
|
||||||
|
httpRequest.SetupGet(req => req.UserHostAddress).Returns("10.4.60.120");
|
||||||
|
httpContext.SetupGet(ctx => ctx.Request).Returns(httpRequest.Object);
|
||||||
|
|
||||||
|
|
||||||
|
var userService = new Mock<IUserService>();
|
||||||
|
userService.Setup(service => service.Save(It.IsAny<User>())).Callback<User>(user => {
|
||||||
|
Assert.That(user, Is.Not.Null);
|
||||||
|
Assert.That(user.Username, Is.Null);
|
||||||
|
Assert.That(user.IpAddress, Is.EqualTo("10.4.60.120"));
|
||||||
|
Assert.That(user.Group, Is.EqualTo(UserGroup.User));
|
||||||
|
}).Returns(new User { Id = 1 });
|
||||||
|
|
||||||
|
var userProvider = new SessionBasedUserProvider(userService.Object, session.Object, httpContext.Object);
|
||||||
|
|
||||||
|
Assert.That(userProvider.CurrentUser, Is.EqualTo(new User { Id = 1 }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>8.0.30703</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{5787E8CA-072D-4231-B34A-B4C92BEEA3E7}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>VideoGameQuotes.Web.Tests</RootNamespace>
|
||||||
|
<AssemblyName>VideoGameQuotes.Web.Tests</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Moq">
|
||||||
|
<HintPath>..\..\Lib\Moq.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="nunit.framework">
|
||||||
|
<HintPath>..\..\Lib\nunit.framework.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Portoa">
|
||||||
|
<HintPath>..\..\Lib\Portoa.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="Portoa.Web">
|
||||||
|
<HintPath>..\..\Lib\Portoa.Web.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Web" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="UserProviderTests.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Src\VideoGameQuotes.Api\VideoGameQuotes.Api.csproj">
|
||||||
|
<Project>{329FAB1F-A18D-4B7B-9E3C-A0C157E55503}</Project>
|
||||||
|
<Name>VideoGameQuotes.Api</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\Src\VideoGameQuotes.Web\VideoGameQuotes.Web.csproj">
|
||||||
|
<Project>{5D576303-EEB3-409B-80E2-FC221C23D7BF}</Project>
|
||||||
|
<Name>VideoGameQuotes.Web</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.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VideoGameQuotes.Api.Tests",
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VideoGameQuotes.Web", "Src\VideoGameQuotes.Web\VideoGameQuotes.Web.csproj", "{5D576303-EEB3-409B-80E2-FC221C23D7BF}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VideoGameQuotes.Web", "Src\VideoGameQuotes.Web\VideoGameQuotes.Web.csproj", "{5D576303-EEB3-409B-80E2-FC221C23D7BF}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VideoGameQuotes.Web.Tests", "Tests\VideoGameQuotes.Web.Tests\VideoGameQuotes.Web.Tests.csproj", "{5787E8CA-072D-4231-B34A-B4C92BEEA3E7}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -25,6 +27,10 @@ Global
|
|||||||
{5D576303-EEB3-409B-80E2-FC221C23D7BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{5D576303-EEB3-409B-80E2-FC221C23D7BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{5D576303-EEB3-409B-80E2-FC221C23D7BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{5D576303-EEB3-409B-80E2-FC221C23D7BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{5D576303-EEB3-409B-80E2-FC221C23D7BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
{5D576303-EEB3-409B-80E2-FC221C23D7BF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5787E8CA-072D-4231-B34A-B4C92BEEA3E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5787E8CA-072D-4231-B34A-B4C92BEEA3E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5787E8CA-072D-4231-B34A-B4C92BEEA3E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5787E8CA-072D-4231-B34A-B4C92BEEA3E7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
Loading…
Reference in New Issue
Block a user