mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-14 02:44:52 +08:00
Merge
--HG-- branch : dev
This commit is contained in:
@@ -206,7 +206,7 @@ namespace Orchard.Specs.Bindings {
|
||||
[When(@"I fill in")]
|
||||
public void WhenIFillIn(Table table) {
|
||||
var inputs = _doc.DocumentNode
|
||||
.SelectNodes("(//input|//textarea)") ?? Enumerable.Empty<HtmlNode>();
|
||||
.SelectNodes("(//input|//textarea|//select)") ?? Enumerable.Empty<HtmlNode>();
|
||||
|
||||
foreach (var row in table.Rows) {
|
||||
var r = row;
|
||||
@@ -244,7 +244,19 @@ namespace Orchard.Specs.Bindings {
|
||||
|
||||
break;
|
||||
default:
|
||||
input.Attributes.Add("value", row["value"]);
|
||||
if (string.Equals(input.Name, "select", StringComparison.OrdinalIgnoreCase)) {
|
||||
var options = input.ChildNodes;
|
||||
foreach (var option in options) {
|
||||
if (option.GetAttributeValue("value", "") == row["value"])
|
||||
option.Attributes.Add("selected", "selected");
|
||||
else if (option.Attributes.Contains("selected"))
|
||||
option.Attributes.Remove("selected");
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
input.Attributes.Add("value", row["value"]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -196,6 +196,11 @@
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>SiteCompilation.feature</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Users.feature.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Users.feature</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UsingSpecFlow.feature.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
@@ -296,6 +301,10 @@
|
||||
<Generator>SpecFlowSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Pages.feature.cs</LastGenOutput>
|
||||
</None>
|
||||
<None Include="Users.feature">
|
||||
<Generator>SpecFlowSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Users.feature.cs</LastGenOutput>
|
||||
</None>
|
||||
<None Include="WebHosting.feature">
|
||||
<Generator>SpecFlowSingleFileGenerator</Generator>
|
||||
<LastGenOutput>WebHosting.feature.cs</LastGenOutput>
|
||||
|
262
src/Orchard.Specs/Users.feature
Normal file
262
src/Orchard.Specs/Users.feature
Normal file
@@ -0,0 +1,262 @@
|
||||
Feature: Users
|
||||
In order to prevent users module regressions
|
||||
As a site owner
|
||||
I want to create, search and modify user accounts
|
||||
|
||||
@management
|
||||
Scenario: There is only one user by default
|
||||
Given I have installed Orchard
|
||||
When I go to "admin/users"
|
||||
Then I should see "Manage Users"
|
||||
And I should see "<a[^>]*>admin</a>"
|
||||
|
||||
@management
|
||||
Scenario: I can create a new user
|
||||
Given I have installed Orchard
|
||||
When I go to "admin/users"
|
||||
Then I should see "Manage Users"
|
||||
When I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user1 |
|
||||
| Email | user1@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
Then I should see "User created"
|
||||
When I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user2 |
|
||||
| Email | user2@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
| UserRoles.Roles[0].Granted | true |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
Then I should see "User created"
|
||||
And I should see "Adding role Administrator to user user2"
|
||||
When I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user3 |
|
||||
| Email | user3@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
| UserRoles.Roles[0].Granted | true |
|
||||
| UserRoles.Roles[1].Granted | true |
|
||||
| UserRoles.Roles[2].Granted | true |
|
||||
| UserRoles.Roles[3].Granted | true |
|
||||
| UserRoles.Roles[4].Granted | true |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
Then I should see "User created"
|
||||
And I should see "Adding role Administrator to user user3"
|
||||
And I should see "Adding role Editor to user user3"
|
||||
And I should see "Adding role Moderator to user user3"
|
||||
And I should see "Adding role Author to user user3"
|
||||
And I should see "Adding role Contributor to user user3"
|
||||
When I follow "Add a new user"
|
||||
And I hit "Save"
|
||||
Then I should see "The UserName field is required."
|
||||
Then I should see "The Email field is required."
|
||||
Then I should see "The Password field is required."
|
||||
Then I should see "The ConfirmPassword field is required."
|
||||
When I go to "admin/users"
|
||||
And I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user4 |
|
||||
| Email | user4@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a123456! |
|
||||
And I hit "Save"
|
||||
Then I should see "Password confirmation must match"
|
||||
|
||||
@management
|
||||
Scenario: I can edit an existing user
|
||||
Given I have installed Orchard
|
||||
When I go to "admin/users"
|
||||
And I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user1 |
|
||||
| Email | user1@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
Then I should see "User created"
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Search | user1 |
|
||||
And I hit "Filter"
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
When I follow "Edit"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user2 |
|
||||
| Email | user2@domain.com |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
Then I should see "User information updated"
|
||||
And I should see "<a[^>]*>user2</a>"
|
||||
And I should see "user2@domain.com"
|
||||
|
||||
@management
|
||||
Scenario: I should not be able to reuse an existing username or email
|
||||
Given I have installed Orchard
|
||||
When I go to "admin/users"
|
||||
# create user1
|
||||
And I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user1 |
|
||||
| Email | user1@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
# create user2
|
||||
And I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user2 |
|
||||
| Email | user2@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
And I should see "<a[^>]*>user2</a>"
|
||||
# filtering on 'user1' to have only one Edit link to follow
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Search | user1 |
|
||||
And I hit "Filter"
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
When I follow "Edit"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user2 |
|
||||
| Email | user1@domain.com |
|
||||
And I hit "Save"
|
||||
Then I should see "User with that username and/or email already exists."
|
||||
When I fill in
|
||||
| name | value |
|
||||
| UserName | user1 |
|
||||
| Email | user2@domain.com |
|
||||
And I hit "Save"
|
||||
Then I should see "User with that username and/or email already exists."
|
||||
|
||||
@filtering
|
||||
Scenario: I should not be able to filter users by name
|
||||
Given I have installed Orchard
|
||||
When I go to "admin/users"
|
||||
# create user1
|
||||
And I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user1 |
|
||||
| Email | user1@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
# create user2
|
||||
And I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user2 |
|
||||
| Email | user2@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
And I should see "<a[^>]*>user2</a>"
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Search | user1 |
|
||||
And I hit "Filter"
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
And I should not see "<a[^>]*>admin</a>"
|
||||
And I should not see "<a[^>]*>user2</a>"
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Search | user1@domain.com |
|
||||
And I hit "Filter"
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
And I should not see "<a[^>]*>admin</a>"
|
||||
And I should not see "<a[^>]*>user2</a>"
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Search | @domain.com |
|
||||
And I hit "Filter"
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
And I should see "<a[^>]*>user2</a>"
|
||||
And I should not see "<a[^>]*>admin</a>"
|
||||
|
||||
@filtering
|
||||
Scenario: I should be able to filter users by status
|
||||
Given I have installed Orchard
|
||||
When I go to "admin/users"
|
||||
# create user1
|
||||
And I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user1 |
|
||||
| Email | user1@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
# create user2
|
||||
And I follow "Add a new user"
|
||||
And I fill in
|
||||
| name | value |
|
||||
| UserName | user2 |
|
||||
| Email | user2@domain.com |
|
||||
| Password | a12345! |
|
||||
| ConfirmPassword | a12345! |
|
||||
And I hit "Save"
|
||||
And I am redirected
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
And I should see "<a[^>]*>user2</a>"
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Search | user1 |
|
||||
And I hit "Filter"
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
When I follow "Disable"
|
||||
And I am redirected
|
||||
Then I should see "User user1 disabled"
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Filter | Pending |
|
||||
And I hit "Filter"
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
And I should not see "<a[^>]*>user2</a>"
|
||||
And I should not see "<a[^>]*>admin</a>"
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Filter | EmailPending |
|
||||
And I hit "Filter"
|
||||
Then I should not see "<a[^>]*>user1</a>"
|
||||
And I should not see "<a[^>]*>user2</a>"
|
||||
And I should not see "<a[^>]*>admin</a>"
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Filter | Approved |
|
||||
And I hit "Filter"
|
||||
Then I should not see "<a[^>]*>user1</a>"
|
||||
And I should see "<a[^>]*>user2</a>"
|
||||
And I should see "<a[^>]*>admin</a>"
|
||||
When I fill in
|
||||
| name | value |
|
||||
| Options.Filter | All |
|
||||
And I hit "Filter"
|
||||
Then I should see "<a[^>]*>user1</a>"
|
||||
And I should see "<a[^>]*>user2</a>"
|
||||
And I should see "<a[^>]*>admin</a>"
|
715
src/Orchard.Specs/Users.feature.cs
generated
Normal file
715
src/Orchard.Specs/Users.feature.cs
generated
Normal file
@@ -0,0 +1,715 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by SpecFlow (http://www.specflow.org/).
|
||||
// SpecFlow Version:1.5.0.0
|
||||
// Runtime Version:4.0.30319.1
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
#region Designer generated code
|
||||
namespace Orchard.Specs
|
||||
{
|
||||
using TechTalk.SpecFlow;
|
||||
|
||||
|
||||
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.5.0.0")]
|
||||
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[NUnit.Framework.TestFixtureAttribute()]
|
||||
[NUnit.Framework.DescriptionAttribute("Users")]
|
||||
public partial class UsersFeature
|
||||
{
|
||||
|
||||
private static TechTalk.SpecFlow.ITestRunner testRunner;
|
||||
|
||||
#line 1 "Users.feature"
|
||||
#line hidden
|
||||
|
||||
[NUnit.Framework.TestFixtureSetUpAttribute()]
|
||||
public virtual void FeatureSetup()
|
||||
{
|
||||
testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
|
||||
TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Users", "In order to prevent users module regressions\nAs a site owner\nI want to create, se" +
|
||||
"arch and modify user accounts", GenerationTargetLanguage.CSharp, ((string[])(null)));
|
||||
testRunner.OnFeatureStart(featureInfo);
|
||||
}
|
||||
|
||||
[NUnit.Framework.TestFixtureTearDownAttribute()]
|
||||
public virtual void FeatureTearDown()
|
||||
{
|
||||
testRunner.OnFeatureEnd();
|
||||
testRunner = null;
|
||||
}
|
||||
|
||||
public virtual void ScenarioSetup(TechTalk.SpecFlow.ScenarioInfo scenarioInfo)
|
||||
{
|
||||
testRunner.OnScenarioStart(scenarioInfo);
|
||||
}
|
||||
|
||||
[NUnit.Framework.TearDownAttribute()]
|
||||
public virtual void ScenarioTearDown()
|
||||
{
|
||||
testRunner.OnScenarioEnd();
|
||||
}
|
||||
|
||||
[NUnit.Framework.TestAttribute()]
|
||||
[NUnit.Framework.DescriptionAttribute("There is only one user by default")]
|
||||
[NUnit.Framework.CategoryAttribute("management")]
|
||||
public virtual void ThereIsOnlyOneUserByDefault()
|
||||
{
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("There is only one user by default", new string[] {
|
||||
"management"});
|
||||
#line 7
|
||||
this.ScenarioSetup(scenarioInfo);
|
||||
#line 8
|
||||
testRunner.Given("I have installed Orchard");
|
||||
#line 9
|
||||
testRunner.When("I go to \"admin/users\"");
|
||||
#line 10
|
||||
testRunner.Then("I should see \"Manage Users\"");
|
||||
#line 11
|
||||
testRunner.And("I should see \"<a[^>]*>admin</a>\"");
|
||||
#line hidden
|
||||
testRunner.CollectScenarioErrors();
|
||||
}
|
||||
|
||||
[NUnit.Framework.TestAttribute()]
|
||||
[NUnit.Framework.DescriptionAttribute("I can create a new user")]
|
||||
[NUnit.Framework.CategoryAttribute("management")]
|
||||
public virtual void ICanCreateANewUser()
|
||||
{
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can create a new user", new string[] {
|
||||
"management"});
|
||||
#line 14
|
||||
this.ScenarioSetup(scenarioInfo);
|
||||
#line 15
|
||||
testRunner.Given("I have installed Orchard");
|
||||
#line 16
|
||||
testRunner.When("I go to \"admin/users\"");
|
||||
#line 17
|
||||
testRunner.Then("I should see \"Manage Users\"");
|
||||
#line 18
|
||||
testRunner.When("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table1.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user1"});
|
||||
table1.AddRow(new string[] {
|
||||
"Email",
|
||||
"user1@domain.com"});
|
||||
table1.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table1.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
#line 19
|
||||
testRunner.And("I fill in", ((string)(null)), table1);
|
||||
#line 25
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 26
|
||||
testRunner.And("I am redirected");
|
||||
#line 27
|
||||
testRunner.Then("I should see \"User created\"");
|
||||
#line 28
|
||||
testRunner.When("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table2.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user2"});
|
||||
table2.AddRow(new string[] {
|
||||
"Email",
|
||||
"user2@domain.com"});
|
||||
table2.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table2.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
table2.AddRow(new string[] {
|
||||
"UserRoles.Roles[0].Granted",
|
||||
"true"});
|
||||
#line 29
|
||||
testRunner.And("I fill in", ((string)(null)), table2);
|
||||
#line 36
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 37
|
||||
testRunner.And("I am redirected");
|
||||
#line 38
|
||||
testRunner.Then("I should see \"User created\"");
|
||||
#line 39
|
||||
testRunner.And("I should see \"Adding role Administrator to user user2\"");
|
||||
#line 40
|
||||
testRunner.When("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table3 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table3.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user3"});
|
||||
table3.AddRow(new string[] {
|
||||
"Email",
|
||||
"user3@domain.com"});
|
||||
table3.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table3.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
table3.AddRow(new string[] {
|
||||
"UserRoles.Roles[0].Granted",
|
||||
"true"});
|
||||
table3.AddRow(new string[] {
|
||||
"UserRoles.Roles[1].Granted",
|
||||
"true"});
|
||||
table3.AddRow(new string[] {
|
||||
"UserRoles.Roles[2].Granted",
|
||||
"true"});
|
||||
table3.AddRow(new string[] {
|
||||
"UserRoles.Roles[3].Granted",
|
||||
"true"});
|
||||
table3.AddRow(new string[] {
|
||||
"UserRoles.Roles[4].Granted",
|
||||
"true"});
|
||||
#line 41
|
||||
testRunner.And("I fill in", ((string)(null)), table3);
|
||||
#line 52
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 53
|
||||
testRunner.And("I am redirected");
|
||||
#line 54
|
||||
testRunner.Then("I should see \"User created\"");
|
||||
#line 55
|
||||
testRunner.And("I should see \"Adding role Administrator to user user3\"");
|
||||
#line 56
|
||||
testRunner.And("I should see \"Adding role Editor to user user3\"");
|
||||
#line 57
|
||||
testRunner.And("I should see \"Adding role Moderator to user user3\"");
|
||||
#line 58
|
||||
testRunner.And("I should see \"Adding role Author to user user3\"");
|
||||
#line 59
|
||||
testRunner.And("I should see \"Adding role Contributor to user user3\"");
|
||||
#line 60
|
||||
testRunner.When("I follow \"Add a new user\"");
|
||||
#line 61
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 62
|
||||
testRunner.Then("I should see \"The UserName field is required.\"");
|
||||
#line 63
|
||||
testRunner.Then("I should see \"The Email field is required.\"");
|
||||
#line 64
|
||||
testRunner.Then("I should see \"The Password field is required.\"");
|
||||
#line 65
|
||||
testRunner.Then("I should see \"The ConfirmPassword field is required.\"");
|
||||
#line 66
|
||||
testRunner.When("I go to \"admin/users\"");
|
||||
#line 67
|
||||
testRunner.And("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table4 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table4.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user4"});
|
||||
table4.AddRow(new string[] {
|
||||
"Email",
|
||||
"user4@domain.com"});
|
||||
table4.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table4.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a123456!"});
|
||||
#line 68
|
||||
testRunner.And("I fill in", ((string)(null)), table4);
|
||||
#line 74
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 75
|
||||
testRunner.Then("I should see \"Password confirmation must match\"");
|
||||
#line hidden
|
||||
testRunner.CollectScenarioErrors();
|
||||
}
|
||||
|
||||
[NUnit.Framework.TestAttribute()]
|
||||
[NUnit.Framework.DescriptionAttribute("I can edit an existing user")]
|
||||
[NUnit.Framework.CategoryAttribute("management")]
|
||||
public virtual void ICanEditAnExistingUser()
|
||||
{
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I can edit an existing user", new string[] {
|
||||
"management"});
|
||||
#line 78
|
||||
this.ScenarioSetup(scenarioInfo);
|
||||
#line 79
|
||||
testRunner.Given("I have installed Orchard");
|
||||
#line 80
|
||||
testRunner.When("I go to \"admin/users\"");
|
||||
#line 81
|
||||
testRunner.And("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table5 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table5.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user1"});
|
||||
table5.AddRow(new string[] {
|
||||
"Email",
|
||||
"user1@domain.com"});
|
||||
table5.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table5.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
#line 82
|
||||
testRunner.And("I fill in", ((string)(null)), table5);
|
||||
#line 88
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 89
|
||||
testRunner.And("I am redirected");
|
||||
#line 90
|
||||
testRunner.Then("I should see \"User created\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table6 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table6.AddRow(new string[] {
|
||||
"Options.Search",
|
||||
"user1"});
|
||||
#line 91
|
||||
testRunner.When("I fill in", ((string)(null)), table6);
|
||||
#line 94
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 95
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 96
|
||||
testRunner.When("I follow \"Edit\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table7 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table7.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user2"});
|
||||
table7.AddRow(new string[] {
|
||||
"Email",
|
||||
"user2@domain.com"});
|
||||
#line 97
|
||||
testRunner.And("I fill in", ((string)(null)), table7);
|
||||
#line 101
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 102
|
||||
testRunner.And("I am redirected");
|
||||
#line 103
|
||||
testRunner.Then("I should see \"User information updated\"");
|
||||
#line 104
|
||||
testRunner.And("I should see \"<a[^>]*>user2</a>\"");
|
||||
#line 105
|
||||
testRunner.And("I should see \"user2@domain.com\"");
|
||||
#line hidden
|
||||
testRunner.CollectScenarioErrors();
|
||||
}
|
||||
|
||||
[NUnit.Framework.TestAttribute()]
|
||||
[NUnit.Framework.DescriptionAttribute("I should not be able to reuse an existing username or email")]
|
||||
[NUnit.Framework.CategoryAttribute("management")]
|
||||
public virtual void IShouldNotBeAbleToReuseAnExistingUsernameOrEmail()
|
||||
{
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I should not be able to reuse an existing username or email", new string[] {
|
||||
"management"});
|
||||
#line 108
|
||||
this.ScenarioSetup(scenarioInfo);
|
||||
#line 109
|
||||
testRunner.Given("I have installed Orchard");
|
||||
#line 110
|
||||
testRunner.When("I go to \"admin/users\"");
|
||||
#line 112
|
||||
testRunner.And("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table8 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table8.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user1"});
|
||||
table8.AddRow(new string[] {
|
||||
"Email",
|
||||
"user1@domain.com"});
|
||||
table8.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table8.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
#line 113
|
||||
testRunner.And("I fill in", ((string)(null)), table8);
|
||||
#line 119
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 120
|
||||
testRunner.And("I am redirected");
|
||||
#line 122
|
||||
testRunner.And("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table9 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table9.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user2"});
|
||||
table9.AddRow(new string[] {
|
||||
"Email",
|
||||
"user2@domain.com"});
|
||||
table9.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table9.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
#line 123
|
||||
testRunner.And("I fill in", ((string)(null)), table9);
|
||||
#line 129
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 130
|
||||
testRunner.And("I am redirected");
|
||||
#line 131
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 132
|
||||
testRunner.And("I should see \"<a[^>]*>user2</a>\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table10 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table10.AddRow(new string[] {
|
||||
"Options.Search",
|
||||
"user1"});
|
||||
#line 134
|
||||
testRunner.When("I fill in", ((string)(null)), table10);
|
||||
#line 137
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 138
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 139
|
||||
testRunner.When("I follow \"Edit\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table11 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table11.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user2"});
|
||||
table11.AddRow(new string[] {
|
||||
"Email",
|
||||
"user1@domain.com"});
|
||||
#line 140
|
||||
testRunner.And("I fill in", ((string)(null)), table11);
|
||||
#line 144
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 145
|
||||
testRunner.Then("I should see \"User with that username and/or email already exists.\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table12 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table12.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user1"});
|
||||
table12.AddRow(new string[] {
|
||||
"Email",
|
||||
"user2@domain.com"});
|
||||
#line 146
|
||||
testRunner.When("I fill in", ((string)(null)), table12);
|
||||
#line 150
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 151
|
||||
testRunner.Then("I should see \"User with that username and/or email already exists.\"");
|
||||
#line hidden
|
||||
testRunner.CollectScenarioErrors();
|
||||
}
|
||||
|
||||
[NUnit.Framework.TestAttribute()]
|
||||
[NUnit.Framework.DescriptionAttribute("I should not be able to filter users by name")]
|
||||
[NUnit.Framework.CategoryAttribute("filtering")]
|
||||
public virtual void IShouldNotBeAbleToFilterUsersByName()
|
||||
{
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I should not be able to filter users by name", new string[] {
|
||||
"filtering"});
|
||||
#line 154
|
||||
this.ScenarioSetup(scenarioInfo);
|
||||
#line 155
|
||||
testRunner.Given("I have installed Orchard");
|
||||
#line 156
|
||||
testRunner.When("I go to \"admin/users\"");
|
||||
#line 158
|
||||
testRunner.And("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table13 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table13.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user1"});
|
||||
table13.AddRow(new string[] {
|
||||
"Email",
|
||||
"user1@domain.com"});
|
||||
table13.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table13.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
#line 159
|
||||
testRunner.And("I fill in", ((string)(null)), table13);
|
||||
#line 165
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 166
|
||||
testRunner.And("I am redirected");
|
||||
#line 168
|
||||
testRunner.And("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table14 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table14.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user2"});
|
||||
table14.AddRow(new string[] {
|
||||
"Email",
|
||||
"user2@domain.com"});
|
||||
table14.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table14.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
#line 169
|
||||
testRunner.And("I fill in", ((string)(null)), table14);
|
||||
#line 175
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 176
|
||||
testRunner.And("I am redirected");
|
||||
#line 177
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 178
|
||||
testRunner.And("I should see \"<a[^>]*>user2</a>\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table15 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table15.AddRow(new string[] {
|
||||
"Options.Search",
|
||||
"user1"});
|
||||
#line 179
|
||||
testRunner.When("I fill in", ((string)(null)), table15);
|
||||
#line 182
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 183
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 184
|
||||
testRunner.And("I should not see \"<a[^>]*>admin</a>\"");
|
||||
#line 185
|
||||
testRunner.And("I should not see \"<a[^>]*>user2</a>\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table16 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table16.AddRow(new string[] {
|
||||
"Options.Search",
|
||||
"user1@domain.com"});
|
||||
#line 186
|
||||
testRunner.When("I fill in", ((string)(null)), table16);
|
||||
#line 189
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 190
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 191
|
||||
testRunner.And("I should not see \"<a[^>]*>admin</a>\"");
|
||||
#line 192
|
||||
testRunner.And("I should not see \"<a[^>]*>user2</a>\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table17 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table17.AddRow(new string[] {
|
||||
"Options.Search",
|
||||
"@domain.com"});
|
||||
#line 193
|
||||
testRunner.When("I fill in", ((string)(null)), table17);
|
||||
#line 196
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 197
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 198
|
||||
testRunner.And("I should see \"<a[^>]*>user2</a>\"");
|
||||
#line 199
|
||||
testRunner.And("I should not see \"<a[^>]*>admin</a>\"");
|
||||
#line hidden
|
||||
testRunner.CollectScenarioErrors();
|
||||
}
|
||||
|
||||
[NUnit.Framework.TestAttribute()]
|
||||
[NUnit.Framework.DescriptionAttribute("I should be able to filter users by status")]
|
||||
[NUnit.Framework.CategoryAttribute("filtering")]
|
||||
public virtual void IShouldBeAbleToFilterUsersByStatus()
|
||||
{
|
||||
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("I should be able to filter users by status", new string[] {
|
||||
"filtering"});
|
||||
#line 202
|
||||
this.ScenarioSetup(scenarioInfo);
|
||||
#line 203
|
||||
testRunner.Given("I have installed Orchard");
|
||||
#line 204
|
||||
testRunner.When("I go to \"admin/users\"");
|
||||
#line 206
|
||||
testRunner.And("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table18 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table18.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user1"});
|
||||
table18.AddRow(new string[] {
|
||||
"Email",
|
||||
"user1@domain.com"});
|
||||
table18.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table18.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
#line 207
|
||||
testRunner.And("I fill in", ((string)(null)), table18);
|
||||
#line 213
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 214
|
||||
testRunner.And("I am redirected");
|
||||
#line 216
|
||||
testRunner.And("I follow \"Add a new user\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table19 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table19.AddRow(new string[] {
|
||||
"UserName",
|
||||
"user2"});
|
||||
table19.AddRow(new string[] {
|
||||
"Email",
|
||||
"user2@domain.com"});
|
||||
table19.AddRow(new string[] {
|
||||
"Password",
|
||||
"a12345!"});
|
||||
table19.AddRow(new string[] {
|
||||
"ConfirmPassword",
|
||||
"a12345!"});
|
||||
#line 217
|
||||
testRunner.And("I fill in", ((string)(null)), table19);
|
||||
#line 223
|
||||
testRunner.And("I hit \"Save\"");
|
||||
#line 224
|
||||
testRunner.And("I am redirected");
|
||||
#line 225
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 226
|
||||
testRunner.And("I should see \"<a[^>]*>user2</a>\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table20 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table20.AddRow(new string[] {
|
||||
"Options.Search",
|
||||
"user1"});
|
||||
#line 227
|
||||
testRunner.When("I fill in", ((string)(null)), table20);
|
||||
#line 230
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 231
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 232
|
||||
testRunner.When("I follow \"Disable\"");
|
||||
#line 233
|
||||
testRunner.And("I am redirected");
|
||||
#line 234
|
||||
testRunner.Then("I should see \"User user1 disabled\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table21 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table21.AddRow(new string[] {
|
||||
"Options.Filter",
|
||||
"Pending"});
|
||||
#line 235
|
||||
testRunner.When("I fill in", ((string)(null)), table21);
|
||||
#line 238
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 239
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 240
|
||||
testRunner.And("I should not see \"<a[^>]*>user2</a>\"");
|
||||
#line 241
|
||||
testRunner.And("I should not see \"<a[^>]*>admin</a>\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table22 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table22.AddRow(new string[] {
|
||||
"Options.Filter",
|
||||
"EmailPending"});
|
||||
#line 242
|
||||
testRunner.When("I fill in", ((string)(null)), table22);
|
||||
#line 245
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 246
|
||||
testRunner.Then("I should not see \"<a[^>]*>user1</a>\"");
|
||||
#line 247
|
||||
testRunner.And("I should not see \"<a[^>]*>user2</a>\"");
|
||||
#line 248
|
||||
testRunner.And("I should not see \"<a[^>]*>admin</a>\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table23 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table23.AddRow(new string[] {
|
||||
"Options.Filter",
|
||||
"Approved"});
|
||||
#line 249
|
||||
testRunner.When("I fill in", ((string)(null)), table23);
|
||||
#line 252
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 253
|
||||
testRunner.Then("I should not see \"<a[^>]*>user1</a>\"");
|
||||
#line 254
|
||||
testRunner.And("I should see \"<a[^>]*>user2</a>\"");
|
||||
#line 255
|
||||
testRunner.And("I should see \"<a[^>]*>admin</a>\"");
|
||||
#line hidden
|
||||
TechTalk.SpecFlow.Table table24 = new TechTalk.SpecFlow.Table(new string[] {
|
||||
"name",
|
||||
"value"});
|
||||
table24.AddRow(new string[] {
|
||||
"Options.Filter",
|
||||
"All"});
|
||||
#line 256
|
||||
testRunner.When("I fill in", ((string)(null)), table24);
|
||||
#line 259
|
||||
testRunner.And("I hit \"Filter\"");
|
||||
#line 260
|
||||
testRunner.Then("I should see \"<a[^>]*>user1</a>\"");
|
||||
#line 261
|
||||
testRunner.And("I should see \"<a[^>]*>user2</a>\"");
|
||||
#line 262
|
||||
testRunner.And("I should see \"<a[^>]*>admin</a>\"");
|
||||
#line hidden
|
||||
testRunner.CollectScenarioErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
@@ -119,14 +119,23 @@ namespace Orchard.Tests.Modules.Indexing {
|
||||
[Test]
|
||||
public void PropertiesShouldNotBeLost() {
|
||||
_provider.CreateIndex("default");
|
||||
_provider.Store("default", _provider.New(42).Add("prop1", "value1").Store());
|
||||
_provider.Store("default", _provider.New(42)
|
||||
.Add("prop1", "value1").Store()
|
||||
.Add("prop2", 123).Store()
|
||||
.Add("prop3", 123.456).Store()
|
||||
.Add("prop4", new DateTime(2001,1,1,1,1,1,1)).Store()
|
||||
.Add("prop5", true).Store()
|
||||
);
|
||||
|
||||
var hit = _provider.CreateSearchBuilder("default").Get(42);
|
||||
|
||||
Assert.IsNotNull(hit);
|
||||
Assert.That(hit.ContentItemId, Is.EqualTo(42));
|
||||
Assert.That(hit.GetString("prop1"), Is.EqualTo("value1"));
|
||||
|
||||
Assert.That(hit.GetInt("prop2"), Is.EqualTo(123));
|
||||
Assert.That(hit.GetDouble("prop3"), Is.EqualTo(123.456));
|
||||
Assert.That(hit.GetDateTime("prop4"), Is.EqualTo(new DateTime(2001, 1, 1, 1, 1, 1, 1)));
|
||||
Assert.That(hit.GetBoolean("prop5"), Is.EqualTo(true));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@@ -177,6 +177,24 @@ namespace Orchard.Tests.Modules.Indexing {
|
||||
Assert.That(date[1].GetDateTime("date") < date[2].GetDateTime("date"), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldSortByNumber() {
|
||||
_provider.CreateIndex("default");
|
||||
_provider.Store("default", _provider.New(1).Add("downloads", 111).Store());
|
||||
_provider.Store("default", _provider.New(2).Add("downloads", 2222).Store());
|
||||
_provider.Store("default", _provider.New(3).Add("downloads", 3).Store());
|
||||
|
||||
var number = _searchBuilder.SortBy("downloads").Search().ToList();
|
||||
Assert.That(number.Count(), Is.EqualTo(3));
|
||||
Assert.That(number[0].GetInt("downloads") > number[1].GetInt("downloads"), Is.True);
|
||||
Assert.That(number[1].GetInt("downloads") > number[2].GetInt("downloads"), Is.True);
|
||||
|
||||
number = _searchBuilder.SortBy("downloads").Ascending().Search().ToList();
|
||||
Assert.That(number.Count(), Is.EqualTo(3));
|
||||
Assert.That(number[0].GetInt("downloads") < number[1].GetInt("downloads"), Is.True);
|
||||
Assert.That(number[1].GetInt("downloads") < number[2].GetInt("downloads"), Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldEscapeSpecialChars() {
|
||||
_provider.CreateIndex("default");
|
||||
|
@@ -166,7 +166,6 @@
|
||||
<Compile Include="Users\Services\UserServiceTests.cs" />
|
||||
<Compile Include="Users\ShellSettingsUtility.cs" />
|
||||
<Compile Include="Values.cs" />
|
||||
<Compile Include="Users\Controllers\AdminControllerTests.cs" />
|
||||
<Compile Include="Users\Services\MembershipServiceTests.cs" />
|
||||
<Compile Include="Widgets\RuleEngine\UrlRuleProviderTest.cs" />
|
||||
<Compile Include="Widgets\Services\WidgetsServiceTest.cs" />
|
||||
|
@@ -1,170 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using System.Xml.Linq;
|
||||
using Autofac;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Caching;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.ContentManagement.MetaData.Models;
|
||||
using Orchard.ContentManagement.MetaData.Services;
|
||||
using Orchard.Core.Settings.Metadata;
|
||||
using Orchard.Data;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.DisplayManagement.Descriptors;
|
||||
using Orchard.DisplayManagement.Implementation;
|
||||
using Orchard.Environment;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.ContentManagement.Records;
|
||||
using Orchard.Environment.Extensions;
|
||||
using Orchard.Localization;
|
||||
using Orchard.Messaging.Events;
|
||||
using Orchard.Messaging.Services;
|
||||
using Orchard.Security;
|
||||
using Orchard.Security.Permissions;
|
||||
using Orchard.Security.Providers;
|
||||
using Orchard.Tests.Stubs;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.Users.Controllers;
|
||||
using Orchard.Users.Handlers;
|
||||
using Orchard.Users.Models;
|
||||
using Orchard.Users.Services;
|
||||
using Orchard.Users.ViewModels;
|
||||
using Orchard.Settings;
|
||||
using Orchard.Core.Settings.Services;
|
||||
|
||||
namespace Orchard.Tests.Modules.Users.Controllers {
|
||||
[TestFixture]
|
||||
public class AdminControllerTests : DatabaseEnabledTestsBase {
|
||||
private AdminController _controller;
|
||||
private Mock<IAuthorizer> _authorizer;
|
||||
|
||||
public override void Register(ContainerBuilder builder) {
|
||||
builder.RegisterType<AdminController>().SingleInstance();
|
||||
builder.RegisterType<SiteService>().As<ISiteService>();
|
||||
builder.RegisterType<StubCacheManager>().As<ICacheManager>();
|
||||
builder.RegisterType<DefaultContentManager>().As<IContentManager>();
|
||||
builder.RegisterType(typeof(SettingsFormatter))
|
||||
.As(typeof(IMapper<XElement, SettingsDictionary>))
|
||||
.As(typeof(IMapper<SettingsDictionary, XElement>));
|
||||
builder.RegisterType<ContentDefinitionManager>().As<IContentDefinitionManager>();
|
||||
builder.RegisterType<DefaultContentManagerSession>().As<IContentManagerSession>();
|
||||
builder.RegisterType<DefaultContentQuery>().As<IContentQuery>().InstancePerDependency();
|
||||
builder.RegisterType<DefaultMessageManager>().As<IMessageManager>();
|
||||
builder.RegisterInstance(new Mock<IMessageEventHandler>().Object);
|
||||
builder.RegisterType<MembershipService>().As<IMembershipService>();
|
||||
builder.RegisterType<UserService>().As<IUserService>();
|
||||
builder.RegisterType<UserPartHandler>().As<IContentHandler>();
|
||||
builder.RegisterType<StubWorkContextAccessor>().As<IWorkContextAccessor>();
|
||||
builder.RegisterType<OrchardServices>().As<IOrchardServices>();
|
||||
builder.RegisterType<TransactionManager>().As<ITransactionManager>();
|
||||
builder.RegisterType<DefaultShapeTableManager>().As<IShapeTableManager>();
|
||||
builder.RegisterType<DefaultShapeFactory>().As<IShapeFactory>();
|
||||
builder.RegisterType<StubExtensionManager>().As<IExtensionManager>();
|
||||
builder.RegisterInstance(new Mock<INotifier>().Object);
|
||||
builder.RegisterInstance(new Mock<IContentDisplay>().Object);
|
||||
builder.RegisterType<StubCacheManager>().As<ICacheManager>();
|
||||
builder.RegisterType<Signals>().As<ISignals>();
|
||||
builder.RegisterType<DefaultEncryptionService>().As<IEncryptionService>();
|
||||
builder.RegisterInstance(ShellSettingsUtility.CreateEncryptionEnabled());
|
||||
|
||||
_authorizer = new Mock<IAuthorizer>();
|
||||
builder.RegisterInstance(_authorizer.Object);
|
||||
}
|
||||
|
||||
protected override IEnumerable<Type> DatabaseTypes {
|
||||
get {
|
||||
return new[] { typeof(UserPartRecord),
|
||||
typeof(ContentTypeRecord),
|
||||
typeof(ContentItemRecord),
|
||||
typeof(ContentItemVersionRecord),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public override void Init() {
|
||||
base.Init();
|
||||
|
||||
var manager = _container.Resolve<IContentManager>();
|
||||
|
||||
var userOne = manager.New<UserPart>("User");
|
||||
userOne.Record = new UserPartRecord { UserName = "one" };
|
||||
manager.Create(userOne.ContentItem);
|
||||
|
||||
var userTwo = manager.New<UserPart>("User");
|
||||
userTwo.Record = new UserPartRecord { UserName = "two" };
|
||||
manager.Create(userTwo.ContentItem);
|
||||
|
||||
var userThree = manager.New<UserPart>("User");
|
||||
userThree.Record = new UserPartRecord { UserName = "three" };
|
||||
manager.Create(userThree.ContentItem);
|
||||
|
||||
_controller = _container.Resolve<AdminController>();
|
||||
|
||||
var mockHttpContext = new Mock<HttpContextBase>();
|
||||
_controller.ControllerContext = new ControllerContext(
|
||||
mockHttpContext.Object,
|
||||
new RouteData(
|
||||
new Route("foo", new MvcRouteHandler()),
|
||||
new MvcRouteHandler()),
|
||||
_controller);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void IndexShouldReturnRowsForUsers() {
|
||||
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
|
||||
|
||||
var controller = _container.Resolve<AdminController>();
|
||||
var result = (ViewResult)controller.Index();
|
||||
var model = (UsersIndexViewModel)result.ViewData.Model;
|
||||
|
||||
Assert.That(model.Rows, Is.Not.Null);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
[Ignore("Needs to instead be a specflow test.")]
|
||||
public void CreateShouldAddUserAndRedirect() {
|
||||
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
|
||||
|
||||
var controller = _container.Resolve<AdminController>();
|
||||
ActionResult result = null; // controller.CreatePOST(new UserCreateViewModel {
|
||||
// UserName = "four",
|
||||
// Email = "six@example.org",
|
||||
// Password = "five",
|
||||
// ConfirmPassword = "five"
|
||||
//});
|
||||
Assert.That(result, Is.TypeOf<RedirectToRouteResult>());
|
||||
|
||||
var redirect = (RedirectToRouteResult)result;
|
||||
var id = Convert.ToInt32(redirect.RouteValues["id"]);
|
||||
var manager = _container.Resolve<IContentManager>();
|
||||
var user = manager.Get(id).As<IUser>();
|
||||
Assert.That(user.UserName, Is.EqualTo("four"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Ignore("Needs fixing. Needs to instead be a specflow test.")]
|
||||
public void EditShouldDisplayUserAndStoreChanges() {
|
||||
_authorizer.Setup(x => x.Authorize(It.IsAny<Permission>(), It.IsAny<LocalizedString>())).Returns(true);
|
||||
|
||||
var repository = _container.Resolve<IRepository<UserPartRecord>>();
|
||||
var id = repository.Get(x => x.UserName == "two").Id;
|
||||
var result = (ViewResult)_container.Resolve<AdminController>().Edit(id);
|
||||
var model = (UserEditViewModel)result.ViewData.Model;
|
||||
//Assert.That(model.UserName, Is.EqualTo("two"));
|
||||
|
||||
var controller = _container.Resolve<AdminController>();
|
||||
controller.ValueProvider = Values.From(new {
|
||||
UserName = "bubba",
|
||||
Email = "hotep",
|
||||
});
|
||||
var result2 = controller.EditPOST(id);
|
||||
Assert.That(result2, Is.TypeOf<RedirectToRouteResult>());
|
||||
}
|
||||
}
|
||||
}
|
@@ -15,7 +15,7 @@ namespace Lucene.Models {
|
||||
private string _name;
|
||||
private string _stringValue;
|
||||
private int _intValue;
|
||||
private float _floatValue;
|
||||
private double _doubleValue;
|
||||
private bool _analyze;
|
||||
private bool _store;
|
||||
private bool _removeTags;
|
||||
@@ -46,7 +46,7 @@ namespace Lucene.Models {
|
||||
}
|
||||
|
||||
public IDocumentIndex Add(string name, DateTime value) {
|
||||
return Add(name, DateTools.DateToString(value, DateTools.Resolution.SECOND));
|
||||
return Add(name, DateTools.DateToString(value, DateTools.Resolution.MILLISECOND));
|
||||
}
|
||||
|
||||
public IDocumentIndex Add(string name, int value) {
|
||||
@@ -62,10 +62,10 @@ namespace Lucene.Models {
|
||||
return Add(name, value.ToString());
|
||||
}
|
||||
|
||||
public IDocumentIndex Add(string name, float value) {
|
||||
public IDocumentIndex Add(string name, double value) {
|
||||
PrepareForIndexing();
|
||||
_name = name;
|
||||
_floatValue = value;
|
||||
_doubleValue = value;
|
||||
_typeCode = TypeCode.Single;
|
||||
IsDirty = true;
|
||||
return this;
|
||||
@@ -114,7 +114,7 @@ namespace Lucene.Models {
|
||||
case TypeCode.Single:
|
||||
Fields.Add(new NumericField(_name,
|
||||
_store ? Field.Store.YES : Field.Store.NO,
|
||||
true).SetFloatValue(_floatValue));
|
||||
true).SetDoubleValue(_doubleValue));
|
||||
break;
|
||||
case TypeCode.Empty:
|
||||
break;
|
||||
|
@@ -20,12 +20,12 @@ namespace Lucene.Models {
|
||||
|
||||
public int GetInt(string name) {
|
||||
var field = _doc.GetField(name);
|
||||
return field == null ? 0 : NumericUtils.PrefixCodedToInt(field.StringValue());
|
||||
return field == null ? 0 : Int32.Parse(field.StringValue(), CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public float GetFloat(string name) {
|
||||
public double GetDouble(string name) {
|
||||
var field = _doc.GetField(name);
|
||||
return field == null ? 0 : float.Parse(field.StringValue(), CultureInfo.InvariantCulture);
|
||||
return field == null ? 0 : double.Parse(field.StringValue(), CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public bool GetBoolean(string name) {
|
||||
|
@@ -24,7 +24,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
private readonly IBlogPostService _blogPostService;
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
private readonly IBlogSlugConstraint _blogSlugConstraint;
|
||||
private readonly IBlogPathConstraint _blogPathConstraint;
|
||||
private readonly ISiteService _siteService;
|
||||
|
||||
public BlogAdminController(
|
||||
@@ -33,7 +33,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
IBlogPostService blogPostService,
|
||||
IContentManager contentManager,
|
||||
ITransactionManager transactionManager,
|
||||
IBlogSlugConstraint blogSlugConstraint,
|
||||
IBlogPathConstraint blogPathConstraint,
|
||||
ISiteService siteService,
|
||||
IShapeFactory shapeFactory) {
|
||||
Services = services;
|
||||
@@ -41,7 +41,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
_blogPostService = blogPostService;
|
||||
_contentManager = contentManager;
|
||||
_transactionManager = transactionManager;
|
||||
_blogSlugConstraint = blogSlugConstraint;
|
||||
_blogPathConstraint = blogPathConstraint;
|
||||
_siteService = siteService;
|
||||
T = NullLocalizer.Instance;
|
||||
Shape = shapeFactory;
|
||||
@@ -81,7 +81,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
}
|
||||
|
||||
_contentManager.Publish(blog.ContentItem);
|
||||
_blogSlugConstraint.AddSlug(blog.As<IRoutableAspect>().GetEffectiveSlug());
|
||||
_blogPathConstraint.AddPath(blog.As<IRoutableAspect>().Path);
|
||||
|
||||
return Redirect(Url.BlogForAdmin(blog));
|
||||
}
|
||||
@@ -116,7 +116,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
}
|
||||
|
||||
_contentManager.Publish(blog);
|
||||
_blogSlugConstraint.AddSlug(blog.As<IRoutableAspect>().GetEffectiveSlug());
|
||||
_blogPathConstraint.AddPath(blog.As<IRoutableAspect>().Path);
|
||||
Services.Notifier.Information(T("Blog information updated"));
|
||||
|
||||
return Redirect(Url.BlogsForAdmin());
|
||||
|
@@ -20,7 +20,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
private readonly IOrchardServices _services;
|
||||
private readonly IBlogService _blogService;
|
||||
private readonly IBlogPostService _blogPostService;
|
||||
private readonly IBlogSlugConstraint _blogSlugConstraint;
|
||||
private readonly IBlogPathConstraint _blogPathConstraint;
|
||||
private readonly IFeedManager _feedManager;
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
private readonly IHomePageProvider _routableHomePageProvider;
|
||||
@@ -30,7 +30,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
IOrchardServices services,
|
||||
IBlogService blogService,
|
||||
IBlogPostService blogPostService,
|
||||
IBlogSlugConstraint blogSlugConstraint,
|
||||
IBlogPathConstraint blogPathConstraint,
|
||||
IFeedManager feedManager,
|
||||
IShapeFactory shapeFactory,
|
||||
IWorkContextAccessor workContextAccessor,
|
||||
@@ -39,7 +39,7 @@ namespace Orchard.Blogs.Controllers {
|
||||
_services = services;
|
||||
_blogService = blogService;
|
||||
_blogPostService = blogPostService;
|
||||
_blogSlugConstraint = blogSlugConstraint;
|
||||
_blogPathConstraint = blogPathConstraint;
|
||||
_feedManager = feedManager;
|
||||
_workContextAccessor = workContextAccessor;
|
||||
_siteService = siteService;
|
||||
@@ -64,13 +64,13 @@ namespace Orchard.Blogs.Controllers {
|
||||
return View((object)viewModel);
|
||||
}
|
||||
|
||||
public ActionResult Item(string blogSlug, PagerParameters pagerParameters) {
|
||||
public ActionResult Item(string blogPath, PagerParameters pagerParameters) {
|
||||
Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||
var correctedSlug = _blogSlugConstraint.FindSlug(blogSlug);
|
||||
if (correctedSlug == null)
|
||||
var correctedPath = _blogPathConstraint.FindPath(blogPath);
|
||||
if (correctedPath == null)
|
||||
return HttpNotFound();
|
||||
|
||||
var blogPart = _blogService.Get(correctedSlug);
|
||||
var blogPart = _blogService.Get(correctedPath);
|
||||
if (blogPart == null)
|
||||
return HttpNotFound();
|
||||
|
||||
|
@@ -36,12 +36,12 @@ namespace Orchard.Blogs.Controllers {
|
||||
public Localizer T { get; set; }
|
||||
|
||||
//TODO: (erikpo) Should think about moving the slug parameters and get calls and null checks up into a model binder or action filter
|
||||
public ActionResult Item(string blogSlug, string postSlug) {
|
||||
public ActionResult Item(string blogPath, string postSlug) {
|
||||
if (!_services.Authorizer.Authorize(StandardPermissions.AccessFrontEnd, T("Couldn't view blog post")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
//TODO: (erikpo) Move looking up the current blog up into a modelbinder
|
||||
var blogPart = _blogService.Get(blogSlug);
|
||||
var blogPart = _blogService.Get(blogPath);
|
||||
if (blogPart == null)
|
||||
return HttpNotFound();
|
||||
|
||||
@@ -55,9 +55,9 @@ namespace Orchard.Blogs.Controllers {
|
||||
return View((object)model);
|
||||
}
|
||||
|
||||
public ActionResult ListByArchive(string blogSlug, string archiveData) {
|
||||
public ActionResult ListByArchive(string blogPath, string archiveData) {
|
||||
//TODO: (erikpo) Move looking up the current blog up into a modelbinder
|
||||
BlogPart blogPart = _blogService.Get(blogSlug);
|
||||
BlogPart blogPart = _blogService.Get(blogPath);
|
||||
|
||||
if (blogPart == null)
|
||||
return HttpNotFound();
|
||||
|
@@ -21,10 +21,10 @@ namespace Orchard.Blogs.Controllers {
|
||||
|
||||
protected ILogger Logger { get; set; }
|
||||
|
||||
public ActionResult Rsd(string blogSlug) {
|
||||
public ActionResult Rsd(string blogPath) {
|
||||
Logger.Debug("RSD requested");
|
||||
|
||||
BlogPart blogPart = _blogService.Get(blogSlug);
|
||||
BlogPart blogPart = _blogService.Get(blogPath);
|
||||
|
||||
if (blogPart == null)
|
||||
return HttpNotFound();
|
||||
|
@@ -1,5 +1,8 @@
|
||||
using Orchard.Blogs.Models;
|
||||
using System.Linq;
|
||||
using Orchard.Blogs.Models;
|
||||
using Orchard.Blogs.Routing;
|
||||
using Orchard.Blogs.Services;
|
||||
using Orchard.Blogs.ViewModels;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
|
||||
@@ -7,18 +10,22 @@ namespace Orchard.Blogs.Drivers {
|
||||
public class BlogArchivesPartDriver : ContentPartDriver<BlogArchivesPart> {
|
||||
private readonly IBlogService _blogService;
|
||||
private readonly IBlogPostService _blogPostService;
|
||||
private readonly IBlogPathConstraint _blogPathConstraint;
|
||||
|
||||
public BlogArchivesPartDriver(IBlogService blogService, IBlogPostService blogPostService) {
|
||||
public BlogArchivesPartDriver(
|
||||
IBlogService blogService,
|
||||
IBlogPostService blogPostService,
|
||||
IBlogPathConstraint blogPathConstraint) {
|
||||
_blogService = blogService;
|
||||
_blogPostService = blogPostService;
|
||||
_blogPathConstraint = blogPathConstraint;
|
||||
}
|
||||
|
||||
protected override DriverResult Display(BlogArchivesPart part, string displayType, dynamic shapeHelper) {
|
||||
return ContentShape("Parts_Blogs_BlogArchives",
|
||||
() => {
|
||||
BlogPart blog = null;
|
||||
if (!string.IsNullOrWhiteSpace(part.ForBlog))
|
||||
blog = _blogService.Get(part.ForBlog);
|
||||
var path = _blogPathConstraint.FindPath(part.ForBlog);
|
||||
BlogPart blog = _blogService.Get(path);
|
||||
|
||||
if (blog == null)
|
||||
return null;
|
||||
@@ -28,12 +35,21 @@ namespace Orchard.Blogs.Drivers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(BlogArchivesPart part, dynamic shapeHelper) {
|
||||
var viewModel = new BlogArchivesViewModel {
|
||||
Path = part.ForBlog,
|
||||
Blogs = _blogService.Get().ToList().OrderBy(b => b.Name)
|
||||
};
|
||||
|
||||
return ContentShape("Parts_Blogs_BlogArchives_Edit",
|
||||
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Blogs.BlogArchives", Model: part, Prefix: Prefix));
|
||||
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Blogs.BlogArchives", Model: viewModel, Prefix: Prefix));
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(BlogArchivesPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
updater.TryUpdateModel(part, Prefix, null, null);
|
||||
var viewModel = new BlogArchivesViewModel();
|
||||
if (updater.TryUpdateModel(viewModel, Prefix, null, null)) {
|
||||
part.ForBlog = viewModel.Path;
|
||||
}
|
||||
|
||||
return Editor(part, shapeHelper);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,8 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Orchard.Blogs.Models;
|
||||
using Orchard.Blogs.Routing;
|
||||
using Orchard.Blogs.Services;
|
||||
using Orchard.Blogs.ViewModels;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.Core.Common.Models;
|
||||
@@ -10,33 +11,30 @@ namespace Orchard.Blogs.Drivers {
|
||||
public class RecentBlogPostsPartDriver : ContentPartDriver<RecentBlogPostsPart> {
|
||||
private readonly IBlogService _blogService;
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly IBlogPathConstraint _blogPathConstraint;
|
||||
|
||||
public RecentBlogPostsPartDriver(IBlogService blogService, IContentManager contentManager) {
|
||||
public RecentBlogPostsPartDriver(
|
||||
IBlogService blogService,
|
||||
IContentManager contentManager,
|
||||
IBlogPathConstraint blogPathConstraint) {
|
||||
_blogService = blogService;
|
||||
_contentManager = contentManager;
|
||||
_blogPathConstraint = blogPathConstraint;
|
||||
}
|
||||
|
||||
protected override DriverResult Display(RecentBlogPostsPart part, string displayType, dynamic shapeHelper) {
|
||||
IEnumerable<BlogPostPart> blogPosts;
|
||||
var path = _blogPathConstraint.FindPath(part.ForBlog);
|
||||
BlogPart blog = _blogService.Get(path);
|
||||
|
||||
BlogPart blog = null;
|
||||
if (!string.IsNullOrWhiteSpace(part.ForBlog))
|
||||
blog = _blogService.Get(part.ForBlog);
|
||||
if (blog == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (blog != null) {
|
||||
blogPosts = _contentManager.Query(VersionOptions.Published, "BlogPost")
|
||||
.Join<CommonPartRecord>().Where(cr => cr.Container == blog.Record.ContentItemRecord)
|
||||
.OrderByDescending(cr => cr.CreatedUtc)
|
||||
.Slice(0, part.Count)
|
||||
.Select(ci => ci.As<BlogPostPart>());
|
||||
}
|
||||
else {
|
||||
blogPosts = _contentManager.Query(VersionOptions.Published, "BlogPost")
|
||||
.Join<CommonPartRecord>()
|
||||
.OrderByDescending(cr => cr.CreatedUtc)
|
||||
.Slice(0, part.Count)
|
||||
.Select(ci => ci.As<BlogPostPart>());
|
||||
}
|
||||
var blogPosts =_contentManager.Query(VersionOptions.Published, "BlogPost")
|
||||
.Join<CommonPartRecord>().Where(cr => cr.Container == blog.Record.ContentItemRecord)
|
||||
.OrderByDescending(cr => cr.CreatedUtc)
|
||||
.Slice(0, part.Count)
|
||||
.Select(ci => ci.As<BlogPostPart>());
|
||||
|
||||
var list = shapeHelper.List();
|
||||
list.AddRange(blogPosts.Select(bp => _contentManager.BuildDisplay(bp, "Summary")));
|
||||
@@ -47,12 +45,23 @@ namespace Orchard.Blogs.Drivers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(RecentBlogPostsPart part, dynamic shapeHelper) {
|
||||
var viewModel = new RecentBlogPostsViewModel {
|
||||
Count = part.Count,
|
||||
Path = part.ForBlog,
|
||||
Blogs = _blogService.Get().ToList().OrderBy(b => b.Name)
|
||||
};
|
||||
|
||||
return ContentShape("Parts_Blogs_RecentBlogPosts_Edit",
|
||||
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Blogs.RecentBlogPosts", Model: part, Prefix: Prefix));
|
||||
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Blogs.RecentBlogPosts", Model: viewModel, Prefix: Prefix));
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(RecentBlogPostsPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
updater.TryUpdateModel(part, Prefix, null, null);
|
||||
var viewModel = new RecentBlogPostsViewModel();
|
||||
if (updater.TryUpdateModel(viewModel, Prefix, null, null)) {
|
||||
part.ForBlog = viewModel.Path;
|
||||
part.Count = viewModel.Count;
|
||||
}
|
||||
|
||||
return Editor(part, shapeHelper);
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ namespace Orchard.Blogs.Extensions {
|
||||
}
|
||||
|
||||
public static string Blog(this UrlHelper urlHelper, BlogPart blogPart) {
|
||||
return urlHelper.Action("Item", "Blog", new { blogSlug = blogPart.As<IRoutableAspect>().Path, area = "Orchard.Blogs" });
|
||||
return urlHelper.Action("Item", "Blog", new { blogPath = blogPart.As<IRoutableAspect>().Path, area = "Orchard.Blogs" });
|
||||
}
|
||||
|
||||
public static string BlogLiveWriterManifest(this UrlHelper urlHelper, BlogPart blogPart) {
|
||||
@@ -24,19 +24,19 @@ namespace Orchard.Blogs.Extensions {
|
||||
}
|
||||
|
||||
public static string BlogRsd(this UrlHelper urlHelper, BlogPart blogPart) {
|
||||
return urlHelper.AbsoluteAction(() => urlHelper.Action("Rsd", "RemoteBlogPublishing", new { blogSlug = blogPart.As<IRoutableAspect>().Path, area = "Orchard.Blogs" }));
|
||||
return urlHelper.AbsoluteAction(() => urlHelper.Action("Rsd", "RemoteBlogPublishing", new { blogPath = blogPart.As<IRoutableAspect>().Path, area = "Orchard.Blogs" }));
|
||||
}
|
||||
|
||||
public static string BlogArchiveYear(this UrlHelper urlHelper, BlogPart blogPart, int year) {
|
||||
return urlHelper.Action("ListByArchive", "BlogPost", new { blogSlug = blogPart.As<IRoutableAspect>().Path, archiveData = year.ToString(), area = "Orchard.Blogs" });
|
||||
return urlHelper.Action("ListByArchive", "BlogPost", new { blogPath = blogPart.As<IRoutableAspect>().Path, archiveData = year.ToString(), area = "Orchard.Blogs" });
|
||||
}
|
||||
|
||||
public static string BlogArchiveMonth(this UrlHelper urlHelper, BlogPart blogPart, int year, int month) {
|
||||
return urlHelper.Action("ListByArchive", "BlogPost", new { blogSlug = blogPart.As<IRoutableAspect>().Path, archiveData = string.Format("{0}/{1}", year, month), area = "Orchard.Blogs" });
|
||||
return urlHelper.Action("ListByArchive", "BlogPost", new { blogPath = blogPart.As<IRoutableAspect>().Path, archiveData = string.Format("{0}/{1}", year, month), area = "Orchard.Blogs" });
|
||||
}
|
||||
|
||||
public static string BlogArchiveDay(this UrlHelper urlHelper, BlogPart blogPart, int year, int month, int day) {
|
||||
return urlHelper.Action("ListByArchive", "BlogPost", new { blogSlug = blogPart.As<IRoutableAspect>().Path, archiveData = string.Format("{0}/{1}/{2}", year, month, day), area = "Orchard.Blogs" });
|
||||
return urlHelper.Action("ListByArchive", "BlogPost", new { blogPath = blogPart.As<IRoutableAspect>().Path, archiveData = string.Format("{0}/{1}/{2}", year, month, day), area = "Orchard.Blogs" });
|
||||
}
|
||||
|
||||
public static string BlogForAdmin(this UrlHelper urlHelper, BlogPart blogPart) {
|
||||
@@ -60,7 +60,7 @@ namespace Orchard.Blogs.Extensions {
|
||||
}
|
||||
|
||||
public static string BlogPost(this UrlHelper urlHelper, BlogPostPart blogPostPart) {
|
||||
return urlHelper.Action("Item", "BlogPost", new { blogSlug = blogPostPart.BlogPart.As<IRoutableAspect>().Path, postSlug = blogPostPart.As<IRoutableAspect>().GetEffectiveSlug(), area = "Orchard.Blogs" });
|
||||
return urlHelper.Action("Item", "BlogPost", new { blogPath = blogPostPart.BlogPart.As<IRoutableAspect>().Path, postSlug = blogPostPart.As<IRoutableAspect>().GetEffectiveSlug(), area = "Orchard.Blogs" });
|
||||
}
|
||||
|
||||
public static string BlogPostEdit(this UrlHelper urlHelper, BlogPostPart blogPostPart) {
|
||||
|
@@ -16,22 +16,22 @@ namespace Orchard.Blogs.Handlers {
|
||||
[UsedImplicitly]
|
||||
public class BlogPartHandler : ContentHandler {
|
||||
private readonly IWorkContextAccessor _workContextAccessor;
|
||||
private readonly IBlogSlugConstraint _blogSlugConstraint;
|
||||
private readonly IBlogPathConstraint _blogPathConstraint;
|
||||
private readonly IHomePageProvider _routableHomePageProvider;
|
||||
|
||||
public BlogPartHandler(IRepository<BlogPartRecord> repository, IWorkContextAccessor workContextAccessor, IEnumerable<IHomePageProvider> homePageProviders, IBlogSlugConstraint blogSlugConstraint) {
|
||||
public BlogPartHandler(IRepository<BlogPartRecord> repository, IWorkContextAccessor workContextAccessor, IEnumerable<IHomePageProvider> homePageProviders, IBlogPathConstraint blogPathConstraint) {
|
||||
_workContextAccessor = workContextAccessor;
|
||||
_blogSlugConstraint = blogSlugConstraint;
|
||||
_blogPathConstraint = blogPathConstraint;
|
||||
_routableHomePageProvider = homePageProviders.SingleOrDefault(p => p.GetProviderName() == RoutableHomePageProvider.Name);
|
||||
Filters.Add(StorageFilter.For(repository));
|
||||
|
||||
Action<PublishContentContext, RoutePart> publishedHandler = (context, route) => {
|
||||
if (route.Is<BlogPart>()) {
|
||||
if (route.ContentItem.Id != 0 && route.PromoteToHomePage)
|
||||
_blogSlugConstraint.AddSlug("");
|
||||
_blogPathConstraint.AddPath("");
|
||||
}
|
||||
else if (route.ContentItem.Id != 0 && route.PromoteToHomePage) {
|
||||
_blogSlugConstraint.RemoveSlug("");
|
||||
_blogPathConstraint.RemovePath("");
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -78,10 +78,10 @@
|
||||
<Compile Include="Handlers\BlogPartArchiveHandler.cs" />
|
||||
<Compile Include="Models\BlogPartArchiveRecord.cs" />
|
||||
<Compile Include="Permissions.cs" />
|
||||
<Compile Include="Routing\IBlogSlugConstraint.cs" />
|
||||
<Compile Include="Routing\IBlogPathConstraint.cs" />
|
||||
<Compile Include="Routing\IsArchiveConstraint.cs" />
|
||||
<Compile Include="Routing\BlogSlugConstraint.cs" />
|
||||
<Compile Include="Routing\BlogSlugConstraintUpdator.cs" />
|
||||
<Compile Include="Routing\BlogPathConstraint.cs" />
|
||||
<Compile Include="Routing\BlogPathConstraintUpdator.cs" />
|
||||
<Compile Include="Security\BlogAuthorizationEventHandler.cs" />
|
||||
<Compile Include="Services\BlogService.cs" />
|
||||
<Compile Include="Controllers\BlogController.cs" />
|
||||
@@ -96,6 +96,8 @@
|
||||
<Compile Include="Services\IBlogPostService.cs" />
|
||||
<Compile Include="Services\IBlogService.cs" />
|
||||
<Compile Include="Services\XmlRpcHandler.cs" />
|
||||
<Compile Include="ViewModels\BlogArchivesViewModel.cs" />
|
||||
<Compile Include="ViewModels\RecentBlogPostsViewModel.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Content\Admin\images\draft.gif" />
|
||||
|
@@ -6,10 +6,10 @@ using Orchard.Mvc.Routes;
|
||||
|
||||
namespace Orchard.Blogs {
|
||||
public class Routes : IRouteProvider {
|
||||
private readonly IBlogSlugConstraint _blogSlugConstraint;
|
||||
private readonly IBlogPathConstraint _blogPathConstraint;
|
||||
|
||||
public Routes(IBlogSlugConstraint blogSlugConstraint) {
|
||||
_blogSlugConstraint = blogSlugConstraint;
|
||||
public Routes(IBlogPathConstraint blogPathConstraint) {
|
||||
_blogPathConstraint = blogPathConstraint;
|
||||
}
|
||||
|
||||
public void GetRoutes(ICollection<RouteDescriptor> routes) {
|
||||
@@ -175,14 +175,31 @@ namespace Orchard.Blogs {
|
||||
},
|
||||
new RouteDescriptor {
|
||||
Route = new Route(
|
||||
"{blogSlug}/Archive/{*archiveData}",
|
||||
"Archive/{*archiveData}",
|
||||
new RouteValueDictionary {
|
||||
{"blogPath", ""},
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "BlogPost"},
|
||||
{"action", "ListByArchive"}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"archiveData", new IsArchiveConstraint()}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"}
|
||||
},
|
||||
new MvcRouteHandler())
|
||||
},
|
||||
new RouteDescriptor {
|
||||
Route = new Route(
|
||||
"{blogPath}/Archive/{*archiveData}",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "BlogPost"},
|
||||
{"action", "ListByArchive"}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"blogSlug", _blogSlugConstraint},
|
||||
{"blogPath", _blogPathConstraint},
|
||||
{"archiveData", new IsArchiveConstraint()}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
@@ -193,14 +210,14 @@ namespace Orchard.Blogs {
|
||||
new RouteDescriptor {
|
||||
Priority = 11,
|
||||
Route = new Route(
|
||||
"{blogSlug}/rsd",
|
||||
"{blogPath}/rsd",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "RemoteBlogPublishing"},
|
||||
{"action", "Rsd"}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"blogSlug", _blogSlugConstraint}
|
||||
{"blogPath", _blogPathConstraint}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"}
|
||||
@@ -210,14 +227,14 @@ namespace Orchard.Blogs {
|
||||
new RouteDescriptor {
|
||||
Priority = 11,
|
||||
Route = new Route(
|
||||
"{blogSlug}/{postSlug}",
|
||||
"{blogPath}/{postSlug}",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "BlogPost"},
|
||||
{"action", "Item"}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"blogSlug", _blogSlugConstraint}
|
||||
{"blogPath", _blogPathConstraint}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"}
|
||||
@@ -227,15 +244,15 @@ namespace Orchard.Blogs {
|
||||
new RouteDescriptor {
|
||||
Priority = 11,
|
||||
Route = new Route(
|
||||
"{blogSlug}",
|
||||
"{blogPath}",
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"},
|
||||
{"controller", "Blog"},
|
||||
{"action", "Item"},
|
||||
{"blogSlug", ""}
|
||||
{"blogPath", ""}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"blogSlug", _blogSlugConstraint}
|
||||
{"blogPath", _blogPathConstraint}
|
||||
},
|
||||
new RouteValueDictionary {
|
||||
{"area", "Orchard.Blogs"}
|
||||
|
@@ -8,46 +8,55 @@ using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Blogs.Routing {
|
||||
[UsedImplicitly]
|
||||
public class BlogSlugConstraint : IBlogSlugConstraint {
|
||||
public class BlogPathConstraint : IBlogPathConstraint {
|
||||
/// <summary>
|
||||
/// Singleton object, per Orchard Shell instance. We need to protect concurrent access to the dictionary.
|
||||
/// </summary>
|
||||
private readonly object _syncLock = new object();
|
||||
private IDictionary<string, string> _slugs = new Dictionary<string, string>();
|
||||
private IDictionary<string, string> _paths = new Dictionary<string, string>();
|
||||
|
||||
public BlogSlugConstraint() {
|
||||
public BlogPathConstraint() {
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public void SetSlugs(IEnumerable<string> slugs) {
|
||||
public void SetPaths(IEnumerable<string> paths) {
|
||||
// Make a copy to avoid performing potential lazy computation inside the lock
|
||||
var slugsArray = slugs.ToArray();
|
||||
var pathArray = paths.ToArray();
|
||||
|
||||
lock (_syncLock) {
|
||||
_slugs = slugsArray.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(value => value, StringComparer.OrdinalIgnoreCase);
|
||||
_paths = pathArray.Distinct(StringComparer.OrdinalIgnoreCase).ToDictionary(value => value, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
Logger.Debug("Blog slugs: {0}", string.Join(", ", slugsArray));
|
||||
Logger.Debug("Blog paths: {0}", string.Join(", ", pathArray));
|
||||
}
|
||||
|
||||
public string FindSlug(string slug) {
|
||||
public string FindPath(string path) {
|
||||
lock (_syncLock) {
|
||||
string actual;
|
||||
return _slugs.TryGetValue(slug, out actual) ? actual : slug;
|
||||
// path can be null for homepage
|
||||
path = path ?? "";
|
||||
|
||||
return _paths.TryGetValue(path, out actual) ? actual : path;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSlug(string slug) {
|
||||
public void AddPath(string path) {
|
||||
lock (_syncLock) {
|
||||
_slugs[slug] = slug;
|
||||
// path can be null for homepage
|
||||
path = path ?? "";
|
||||
|
||||
_paths[path] = path;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveSlug(string slug) {
|
||||
public void RemovePath(string path) {
|
||||
lock (_syncLock) {
|
||||
_slugs.Remove(slug);
|
||||
// path can be null for homepage
|
||||
path = path ?? "";
|
||||
|
||||
_paths.Remove(path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +69,7 @@ namespace Orchard.Blogs.Routing {
|
||||
var parameterValue = Convert.ToString(value);
|
||||
|
||||
lock (_syncLock) {
|
||||
return _slugs.ContainsKey(parameterValue);
|
||||
return _paths.ContainsKey(parameterValue);
|
||||
}
|
||||
}
|
||||
|
@@ -8,12 +8,12 @@ using Orchard.Tasks;
|
||||
|
||||
namespace Orchard.Blogs.Routing {
|
||||
[UsedImplicitly]
|
||||
public class BlogSlugConstraintUpdator : IOrchardShellEvents, IBackgroundTask {
|
||||
private readonly IBlogSlugConstraint _blogSlugConstraint;
|
||||
public class BlogPathConstraintUpdator : IOrchardShellEvents, IBackgroundTask {
|
||||
private readonly IBlogPathConstraint _blogPathConstraint;
|
||||
private readonly IBlogService _blogService;
|
||||
|
||||
public BlogSlugConstraintUpdator(IBlogSlugConstraint blogSlugConstraint, IBlogService blogService) {
|
||||
_blogSlugConstraint = blogSlugConstraint;
|
||||
public BlogPathConstraintUpdator(IBlogPathConstraint blogPathConstraint, IBlogService blogService) {
|
||||
_blogPathConstraint = blogPathConstraint;
|
||||
_blogService = blogService;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Orchard.Blogs.Routing {
|
||||
}
|
||||
|
||||
private void Refresh() {
|
||||
_blogSlugConstraint.SetSlugs(_blogService.Get().Select(b => b.As<IRoutableAspect>().Path));
|
||||
_blogPathConstraint.SetPaths(_blogService.Get().Select(b => b.As<IRoutableAspect>().Slug));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace Orchard.Blogs.Routing {
|
||||
public interface IBlogPathConstraint : IRouteConstraint, ISingletonDependency {
|
||||
void SetPaths(IEnumerable<string> paths);
|
||||
string FindPath(string path);
|
||||
void AddPath(string path);
|
||||
void RemovePath(string path);
|
||||
}
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Web.Routing;
|
||||
|
||||
namespace Orchard.Blogs.Routing {
|
||||
public interface IBlogSlugConstraint : IRouteConstraint, ISingletonDependency {
|
||||
void SetSlugs(IEnumerable<string> slugs);
|
||||
string FindSlug(string slug);
|
||||
void AddSlug(string slug);
|
||||
void RemoveSlug(string slug);
|
||||
}
|
||||
}
|
@@ -29,9 +29,9 @@ namespace Orchard.Blogs.Services {
|
||||
}
|
||||
|
||||
public BlogPostPart Get(BlogPart blogPart, string slug, VersionOptions versionOptions) {
|
||||
var postSlug = blogPart.As<IRoutableAspect>().GetChildPath(slug);
|
||||
var postPath = blogPart.As<IRoutableAspect>().GetChildPath(slug);
|
||||
return
|
||||
_contentManager.Query(versionOptions, "BlogPost").Join<RoutePartRecord>().Where(rr => rr.Path == postSlug).
|
||||
_contentManager.Query(versionOptions, "BlogPost").Join<RoutePartRecord>().Where(rr => rr.Path == postPath).
|
||||
Join<CommonPartRecord>().Where(cr => cr.Container == blogPart.Record.ContentItemRecord).List().
|
||||
SingleOrDefault().As<BlogPostPart>();
|
||||
}
|
||||
|
@@ -11,11 +11,11 @@ namespace Orchard.Blogs.Services {
|
||||
[UsedImplicitly]
|
||||
public class BlogService : IBlogService {
|
||||
private readonly IContentManager _contentManager;
|
||||
private readonly IBlogSlugConstraint _blogSlugConstraint;
|
||||
private readonly IBlogPathConstraint _blogPathConstraint;
|
||||
|
||||
public BlogService(IContentManager contentManager, IBlogSlugConstraint blogSlugConstraint) {
|
||||
public BlogService(IContentManager contentManager, IBlogPathConstraint blogPathConstraint) {
|
||||
_contentManager = contentManager;
|
||||
_blogSlugConstraint = blogSlugConstraint;
|
||||
_blogPathConstraint = blogPathConstraint;
|
||||
}
|
||||
|
||||
public BlogPart Get(string path) {
|
||||
@@ -39,9 +39,15 @@ namespace Orchard.Blogs.Services {
|
||||
.List();
|
||||
}
|
||||
|
||||
public BlogPart GetFromSlug(string slug) {
|
||||
return _contentManager.Query<BlogPart, BlogPartRecord>()
|
||||
.Join<RoutePartRecord>().Where(rr => rr.Slug == slug)
|
||||
.List().FirstOrDefault();
|
||||
}
|
||||
|
||||
public void Delete(ContentItem blog) {
|
||||
_contentManager.Remove(blog);
|
||||
_blogSlugConstraint.RemoveSlug(blog.As<IRoutableAspect>().Path);
|
||||
_blogPathConstraint.RemovePath(blog.As<IRoutableAspect>().Path);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Blogs.Models;
|
||||
|
||||
namespace Orchard.Blogs.ViewModels {
|
||||
public class BlogArchivesViewModel {
|
||||
public string Path { get; set; }
|
||||
public IEnumerable<BlogPart> Blogs { get; set; }
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Blogs.Models;
|
||||
|
||||
namespace Orchard.Blogs.ViewModels {
|
||||
public class RecentBlogPostsViewModel {
|
||||
public int Count { get; set; }
|
||||
public string Path { get; set; }
|
||||
public IEnumerable<BlogPart> Blogs { get; set; }
|
||||
}
|
||||
}
|
@@ -1,8 +1,17 @@
|
||||
@model Orchard.Blogs.Models.BlogArchivesPart
|
||||
@model Orchard.Blogs.ViewModels.BlogArchivesViewModel
|
||||
|
||||
@using Orchard.Blogs.Models;
|
||||
@using Orchard.Core.Routable.Models;
|
||||
@using Orchard.ContentManagement;
|
||||
|
||||
<fieldset>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.ForBlog, T("For Blog"))
|
||||
@Html.TextBoxFor(m => m.ForBlog)
|
||||
<span class="hint">@T("Show the archives for which blog? Note: specify the blog's slug.")</span>
|
||||
@Html.LabelFor(m => m.Slug, T("For Blog"))
|
||||
<select id="@Html.FieldIdFor(m => m.Slug)" name="@Html.FieldNameFor(m => m.Slug)">
|
||||
@foreach(BlogPart blog in Model.Blogs) {
|
||||
@Html.SelectOption(Model.Slug, blog.As<RoutePart>().Slug, blog.Name)
|
||||
}
|
||||
</select>
|
||||
<span class="hint">@T("Select which blog you want to display the archives for")</span>
|
||||
</div>
|
||||
</fieldset>
|
@@ -1,8 +1,18 @@
|
||||
@model Orchard.Blogs.Models.RecentBlogPostsPart
|
||||
@model Orchard.Blogs.ViewModels.RecentBlogPostsViewModel
|
||||
|
||||
@using Orchard.Blogs.Models;
|
||||
@using Orchard.Core.Routable.Models;
|
||||
@using Orchard.ContentManagement;
|
||||
|
||||
<fieldset>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.ForBlog, T("For Blog"))
|
||||
@Html.TextBoxFor(m => m.ForBlog)
|
||||
@Html.LabelFor(m => m.Path, T("For Blog"))
|
||||
<select id="@Html.FieldIdFor(m => m.Path)" name="@Html.FieldNameFor(m => m.Path)">
|
||||
@foreach(BlogPart blog in Model.Blogs) {
|
||||
@Html.SelectOption(Model.Path, blog.As<RoutePart>().Path, blog.Name)
|
||||
}
|
||||
</select>
|
||||
<span class="hint">@T("Select which blog you want to display the recent posts for")</span>
|
||||
</div>
|
||||
<div>
|
||||
@Html.LabelFor(m => m.Count, T("Count"))
|
||||
|
@@ -1,6 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.Core.Common.Models;
|
||||
using Orchard.Core.Contents.Controllers;
|
||||
using Orchard.Core.Settings.Models;
|
||||
using Orchard.DisplayManagement;
|
||||
using Orchard.Localization;
|
||||
@@ -12,6 +16,7 @@ using Orchard.Users.ViewModels;
|
||||
using Orchard.Mvc.Extensions;
|
||||
using System;
|
||||
using Orchard.Settings;
|
||||
using Orchard.UI.Navigation;
|
||||
|
||||
namespace Orchard.Users.Controllers {
|
||||
[ValidateInput(false)]
|
||||
@@ -39,24 +44,107 @@ namespace Orchard.Users.Controllers {
|
||||
public IOrchardServices Services { get; set; }
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult Index() {
|
||||
public ActionResult Index(UserIndexOptions options, PagerParameters pagerParameters) {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||
|
||||
// default options
|
||||
if (options == null)
|
||||
options = new UserIndexOptions();
|
||||
|
||||
var users = Services.ContentManager
|
||||
.Query<UserPart, UserPartRecord>()
|
||||
.Where(x => x.UserName != null)
|
||||
.List();
|
||||
.Query<UserPart, UserPartRecord>();
|
||||
|
||||
switch (options.Filter) {
|
||||
case UsersFilter.Approved:
|
||||
users = users.Where(u => u.RegistrationStatus == UserStatus.Approved);
|
||||
break;
|
||||
case UsersFilter.Pending:
|
||||
users = users.Where(u => u.RegistrationStatus == UserStatus.Pending);
|
||||
break;
|
||||
case UsersFilter.EmailPending:
|
||||
users = users.Where(u => u.EmailStatus == UserStatus.Approved);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!String.IsNullOrWhiteSpace(options.Search)) {
|
||||
users = users.Where(u => u.UserName.Contains(options.Search) || u.Email.Contains(options.Search));
|
||||
}
|
||||
|
||||
var pagerShape = Shape.Pager(pager).TotalItemCount(users.Count());
|
||||
|
||||
switch (options.Order) {
|
||||
case UsersOrder.Name:
|
||||
users = users.OrderBy(u => u.UserName);
|
||||
break;
|
||||
case UsersOrder.Email:
|
||||
users = users.OrderBy(u => u.Email);
|
||||
break;
|
||||
}
|
||||
|
||||
var results = users
|
||||
.Slice(pager.GetStartIndex(), pager.PageSize)
|
||||
.ToList();
|
||||
|
||||
var model = new UsersIndexViewModel {
|
||||
Rows = users
|
||||
.Select(x => new UsersIndexViewModel.Row { UserPart = x })
|
||||
.ToList()
|
||||
Users = results
|
||||
.Select(x => new UserEntry { User = x.Record })
|
||||
.ToList(),
|
||||
Options = options,
|
||||
Pager = pagerShape
|
||||
};
|
||||
|
||||
// maintain previous route data when generating page links
|
||||
var routeData = new RouteData();
|
||||
routeData.Values.Add("Options.Filter", options.Filter);
|
||||
routeData.Values.Add("Options.Search", options.Search);
|
||||
routeData.Values.Add("Options.Order", options.Order);
|
||||
|
||||
pagerShape.RouteData(routeData);
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[FormValueRequired("submit.BulkEdit")]
|
||||
public ActionResult Index(FormCollection input) {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var viewModel = new UsersIndexViewModel {Users = new List<UserEntry>(), Options = new UserIndexOptions()};
|
||||
UpdateModel(viewModel);
|
||||
|
||||
var checkedEntries = viewModel.Users.Where(c => c.IsChecked);
|
||||
switch (viewModel.Options.BulkAction) {
|
||||
case UsersBulkAction.None:
|
||||
break;
|
||||
case UsersBulkAction.Approve:
|
||||
foreach (var entry in checkedEntries) {
|
||||
Approve(entry.User.Id);
|
||||
}
|
||||
break;
|
||||
case UsersBulkAction.Disable:
|
||||
foreach (var entry in checkedEntries) {
|
||||
Moderate(entry.User.Id);
|
||||
}
|
||||
break;
|
||||
case UsersBulkAction.ChallengeEmail:
|
||||
foreach (var entry in checkedEntries) {
|
||||
SendChallengeEmail(entry.User.Id);
|
||||
}
|
||||
break;
|
||||
case UsersBulkAction.Delete:
|
||||
foreach (var entry in checkedEntries) {
|
||||
Delete(entry.User.Id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return Index(viewModel.Options, new PagerParameters());
|
||||
}
|
||||
|
||||
public ActionResult Create() {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
@@ -109,7 +197,7 @@ namespace Orchard.Users.Controllers {
|
||||
}
|
||||
|
||||
Services.Notifier.Information(T("User created"));
|
||||
return RedirectToAction("edit", new { user.Id });
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
public ActionResult Edit(int id) {
|
||||
@@ -163,7 +251,7 @@ namespace Orchard.Users.Controllers {
|
||||
}
|
||||
|
||||
Services.Notifier.Information(T("User information updated"));
|
||||
return RedirectToAction("Edit", new { id });
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
public ActionResult Delete(int id) {
|
||||
@@ -181,7 +269,7 @@ namespace Orchard.Users.Controllers {
|
||||
}
|
||||
else{
|
||||
Services.ContentManager.Remove(user.ContentItem);
|
||||
Services.Notifier.Information(T("User deleted"));
|
||||
Services.Notifier.Information(T("User {0} deleted", user.UserName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,13 +280,13 @@ namespace Orchard.Users.Controllers {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var user = Services.ContentManager.Get(id);
|
||||
var user = Services.ContentManager.Get<IUser>(id);
|
||||
|
||||
if ( user != null ) {
|
||||
_userService.SendChallengeEmail(user.As<UserPart>(), nonce => Url.AbsoluteAction(() => Url.Action("ChallengeEmail", "Account", new {Area = "Orchard.Users", nonce = nonce})));
|
||||
Services.Notifier.Information(T("Challenge email sent to {0}", user.UserName));
|
||||
}
|
||||
|
||||
Services.Notifier.Information(T("Challenge email sent"));
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
@@ -207,11 +295,11 @@ namespace Orchard.Users.Controllers {
|
||||
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to manage users")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var user = Services.ContentManager.Get(id);
|
||||
var user = Services.ContentManager.Get<IUser>(id);
|
||||
|
||||
if ( user != null ) {
|
||||
user.As<UserPart>().RegistrationStatus = UserStatus.Approved;
|
||||
Services.Notifier.Information(T("User approved"));
|
||||
Services.Notifier.Information(T("User {0} approved", user.UserName));
|
||||
}
|
||||
|
||||
return RedirectToAction("Index");
|
||||
|
@@ -4,10 +4,40 @@ using Orchard.Users.Models;
|
||||
namespace Orchard.Users.ViewModels {
|
||||
|
||||
public class UsersIndexViewModel {
|
||||
public class Row {
|
||||
public UserPart UserPart { get; set; }
|
||||
}
|
||||
public IList<UserEntry> Users { get; set; }
|
||||
public UserIndexOptions Options { get; set; }
|
||||
public dynamic Pager { get; set; }
|
||||
}
|
||||
|
||||
public IList<Row> Rows { get; set; }
|
||||
public class UserEntry {
|
||||
public UserPartRecord User { get; set; }
|
||||
public bool IsChecked { get; set; }
|
||||
}
|
||||
|
||||
public class UserIndexOptions {
|
||||
public string Search { get; set; }
|
||||
public UsersOrder Order { get; set; }
|
||||
public UsersFilter Filter { get; set; }
|
||||
public UsersBulkAction BulkAction { get; set; }
|
||||
}
|
||||
|
||||
public enum UsersOrder {
|
||||
Name,
|
||||
Email
|
||||
}
|
||||
|
||||
public enum UsersFilter {
|
||||
All,
|
||||
Approved,
|
||||
Pending,
|
||||
EmailPending
|
||||
}
|
||||
|
||||
public enum UsersBulkAction {
|
||||
None,
|
||||
Delete,
|
||||
Disable,
|
||||
Approve,
|
||||
ChallengeEmail
|
||||
}
|
||||
}
|
||||
|
@@ -1,52 +1,101 @@
|
||||
@model Orchard.Users.ViewModels.UsersIndexViewModel
|
||||
@using Orchard.Users.Models;
|
||||
@using Orchard.Users.ViewModels;
|
||||
|
||||
@{
|
||||
var userIndex = 0;
|
||||
|
||||
var pageSizes = new List<int?>() { 10, 50, 100 };
|
||||
var defaultPageSize = WorkContext.CurrentSite.PageSize;
|
||||
if(!pageSizes.Contains(defaultPageSize)) {
|
||||
pageSizes.Add(defaultPageSize);
|
||||
}
|
||||
}
|
||||
|
||||
<h1>@Html.TitleForPage(T("Manage Users").ToString()) </h1>
|
||||
@using (Html.BeginFormAntiForgeryPost()) {
|
||||
@Html.ValidationSummary()
|
||||
<div class="manage">@Html.ActionLink(T("Add a new user").ToString(), "Create", new { }, new { @class = "button primaryAction" })</div>
|
||||
<fieldset>
|
||||
|
||||
<fieldset class="bulk-actions">
|
||||
<label for="publishActions">@T("Actions:")</label>
|
||||
<select id="publishActions" name="@Html.NameOf(m => m.Options.BulkAction)">
|
||||
@Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.None, T("Choose action...").ToString())
|
||||
@Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.Approve, T("Approve").ToString())
|
||||
@Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.Disable, T("Disable").ToString())
|
||||
@Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.ChallengeEmail, T("Send challenge E-mail").ToString())
|
||||
@Html.SelectOption(Model.Options.BulkAction, UsersBulkAction.Delete, T("Remove").ToString())
|
||||
</select>
|
||||
<button type="submit" name="submit.BulkEdit" value="@T("Apply")">@T("Apply")</button>
|
||||
</fieldset>
|
||||
<fieldset class="bulk-actions">
|
||||
@Html.TextBoxFor(m => m.Options.Search, new { @class = "text"})
|
||||
<label for="filterResults">@T("Filter:")</label>
|
||||
<select id="filterResults" name="@Html.NameOf(m => m.Options.Filter)">
|
||||
@Html.SelectOption(Model.Options.Filter, UsersFilter.All, T("All Users").ToString())
|
||||
@Html.SelectOption(Model.Options.Filter, UsersFilter.Approved, T("Approved Users").ToString())
|
||||
@Html.SelectOption(Model.Options.Filter, UsersFilter.Pending, T("Pending Users").ToString())
|
||||
@Html.SelectOption(Model.Options.Filter, UsersFilter.EmailPending, T("Pending Emails").ToString())
|
||||
</select>
|
||||
<label for="filterResults">@T("Sort by:")</label>
|
||||
<select id="filterResults" name="@Html.NameOf(m => m.Options.Order)">
|
||||
@Html.SelectOption(Model.Options.Order, UsersOrder.Name, T("Name").ToString())
|
||||
@Html.SelectOption(Model.Options.Order, UsersOrder.Email, T("Email").ToString())
|
||||
</select>
|
||||
<input type="hidden" name="Page" value="1" />
|
||||
<label for="pageSize">@T("Show:")</label>
|
||||
<select id="pageSize" name="PageSize">
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, 0, T("All").ToString())
|
||||
@foreach(int size in pageSizes.OrderBy(p => p)) {
|
||||
@Html.SelectOption((int)Model.Pager.PageSize, size, size.ToString())
|
||||
}
|
||||
<select>
|
||||
<button type="submit" name="submit.Filter" value="@T("Filter")">@T("Filter")</button>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<table class="items">
|
||||
<colgroup>
|
||||
<col id="Name" />
|
||||
<col id="Email" />
|
||||
<col id="Edit" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"> ↓</th>
|
||||
<th scope="col">@T("Name")</th>
|
||||
<th scope="col">@T("Email")</th>
|
||||
<th scope="col">@T("") </th>
|
||||
<th scope="col">@T("Actions")</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@foreach (var row in Model.Rows) {
|
||||
<tr>
|
||||
@foreach (var entry in Model.Users) {
|
||||
<tr>
|
||||
<td>
|
||||
@if(row.UserPart.RegistrationStatus == UserStatus.Approved && row.UserPart.EmailStatus == UserStatus.Approved) {
|
||||
<input type="hidden" value="@Model.Users[userIndex].User.Id" name="@Html.NameOf(m => m.Users[userIndex].User.Id)"/>
|
||||
<input type="checkbox" value="true" name="@Html.NameOf(m => m.Users[userIndex].IsChecked)"/>
|
||||
</td>
|
||||
<td>
|
||||
@if(entry.User.RegistrationStatus == UserStatus.Approved && entry.User.EmailStatus == UserStatus.Approved) {
|
||||
<img class="icon" src="@Href("~/Modules/Orchard.Users/Content/Admin/images/online.gif") " alt="@T("Approved") " title="@T("User is approved") " />
|
||||
}
|
||||
else {
|
||||
<img class="icon" src="@Href("~/Modules/Orchard.Users/Content/Admin/images/offline.gif") " alt="@T("Moderated") " title="@if(row.UserPart.EmailStatus == UserStatus.Approved) { @T("User is moderated") } else { @T("E-mail validation is pending") }" />
|
||||
<img class="icon" src="@Href("~/Modules/Orchard.Users/Content/Admin/images/offline.gif") " alt="@T("Moderated") " title="@if(entry.User.EmailStatus == UserStatus.Approved) { @T("User is moderated") } else { @T("E-mail validation is pending") }" />
|
||||
}
|
||||
@Html.ActionLink(row.UserPart.UserName, "Edit", new { row.UserPart.Id })
|
||||
@Html.ActionLink(entry.User.UserName, "Edit", new { entry.User.Id })
|
||||
</td>
|
||||
<td>
|
||||
@row.UserPart.Email
|
||||
@entry.User.Email
|
||||
</td>
|
||||
<td>
|
||||
@Html.ActionLink(T("Edit").ToString(), "Edit", new { row.UserPart.Id }) |
|
||||
@Html.ActionLink(T("Remove").ToString(), "Delete", new { row.UserPart.Id }) |
|
||||
@if(row.UserPart.RegistrationStatus == UserStatus.Pending) {
|
||||
@Html.ActionLink(T("Approve").ToString(), "Approve", new { row.UserPart.Id })
|
||||
@Html.ActionLink(T("Edit").ToString(), "Edit", new { entry.User.Id }) |
|
||||
@Html.ActionLink(T("Remove").ToString(), "Delete", new { entry.User.Id }) |
|
||||
@if(entry.User.RegistrationStatus == UserStatus.Pending) {
|
||||
@Html.ActionLink(T("Approve").ToString(), "Approve", new { entry.User.Id })
|
||||
} else {
|
||||
@Html.ActionLink(T("Disable").ToString(), "Moderate", new { row.UserPart.Id })
|
||||
@Html.ActionLink(T("Disable").ToString(), "Moderate", new { entry.User.Id })
|
||||
}
|
||||
@if ( row.UserPart.EmailStatus == UserStatus.Pending ) { <text>|</text>
|
||||
@Html.ActionLink(T("Send challenge E-mail").ToString(), "SendChallengeEmail", new { row.UserPart.Id })
|
||||
@if ( entry.User.EmailStatus == UserStatus.Pending ) { <text>|</text>
|
||||
@Html.ActionLink(T("Send challenge E-mail").ToString(), "SendChallengeEmail", new { entry.User.Id })
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
userIndex++;
|
||||
}
|
||||
</table>
|
||||
@Display(Model.Pager)
|
||||
</fieldset>
|
||||
}
|
@@ -1,4 +1,5 @@
|
||||
@{
|
||||
var window = 7; // number of simultaneously displayed pages
|
||||
var nextText = HasText(Model.NextText) ? Model.NextText : T(">").Text;
|
||||
var previousText = HasText(Model.PreviousText) ? Model.PreviousText : T("<").Text;
|
||||
|
||||
@@ -18,13 +19,36 @@
|
||||
}
|
||||
|
||||
var totalPageCount = (int) Math.Ceiling((double) Model.TotalItemCount / Model.PageSize);
|
||||
var firstPage = Math.Max(1, (int)Model.Page - (window/2));
|
||||
var lastPage = Math.Min(totalPageCount, (int)Model.Page + (window/2));
|
||||
|
||||
Model.Classes.Add("pager");
|
||||
Model.Classes.Add("group");
|
||||
var tag = Tag(Model, "ul");
|
||||
|
||||
if(Model.RouteData != null) {
|
||||
foreach(var rd in Model.RouteData.Values) {
|
||||
routeData[rd.Key] = rd.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@if (Model.TotalItemCount > 1) {
|
||||
<span class="page-results">@T("Showing items {0} - {1} of {2}", (Model.Page-1)*(int)Model.PageSize + 1, Model.PageSize == 0 ? Model.TotalItemCount : Math.Min(Model.TotalItemCount, (Model.Page)*(int)Model.PageSize), Model.TotalItemCount)</span>
|
||||
}
|
||||
|
||||
@if (totalPageCount > 1) {
|
||||
routeData["pageSize"] = Model.PageSize;
|
||||
@tag.StartElement
|
||||
// first
|
||||
if(firstPage > 1) {
|
||||
if (routeData.ContainsKey("page")) {
|
||||
routeData.Remove("page");
|
||||
}
|
||||
<li class="page-first">
|
||||
@Html.ActionLink(T("<<").Text, (string)routeData["action"], (string)routeData["controller"], routeData, null)
|
||||
</li>
|
||||
}
|
||||
// previous page
|
||||
if(Model.Page > 1) {
|
||||
if (Model.Page == 2 && routeData.ContainsKey("page")) {
|
||||
@@ -38,7 +62,7 @@
|
||||
</li>
|
||||
}
|
||||
// page numbers
|
||||
for (var p = 1; p <= totalPageCount; p++) {
|
||||
for (var p = firstPage; p <= lastPage; p++) {
|
||||
<li class="page-@p">
|
||||
@if (p == Model.Page) {
|
||||
<span>@p</span>
|
||||
@@ -61,5 +85,12 @@
|
||||
@Html.ActionLink((string)nextText, (string)routeData["action"], (string)routeData["controller"], routeData, null)
|
||||
</li>
|
||||
}
|
||||
// last page
|
||||
if(lastPage < totalPageCount) {
|
||||
routeData["page"] = totalPageCount;
|
||||
<li class="page-last">
|
||||
@Html.ActionLink(T(">>").Text, (string)routeData["action"], (string)routeData["controller"], routeData, null)
|
||||
</li>
|
||||
}
|
||||
@tag.EndElement
|
||||
}
|
@@ -10,7 +10,7 @@ namespace Orchard.Indexing {
|
||||
IDocumentIndex Add(string name, DateTime value);
|
||||
IDocumentIndex Add(string name, int value);
|
||||
IDocumentIndex Add(string name, bool value);
|
||||
IDocumentIndex Add(string name, float value);
|
||||
IDocumentIndex Add(string name, double value);
|
||||
|
||||
/// <summary>
|
||||
/// Stores the original value to the index.
|
||||
|
@@ -5,7 +5,7 @@ namespace Orchard.Indexing {
|
||||
float Score { get; }
|
||||
|
||||
int GetInt(string name);
|
||||
float GetFloat(string name);
|
||||
double GetDouble(string name);
|
||||
bool GetBoolean(string name);
|
||||
string GetString(string name);
|
||||
DateTime GetDateTime(string name);
|
||||
|
Reference in New Issue
Block a user