--HG--
branch : 1.x
This commit is contained in:
Renaud Paquay
2011-01-07 23:52:32 -08:00
49 changed files with 1679 additions and 501 deletions

View File

@@ -114,6 +114,10 @@
<Reference Include="System.Web.WebPages">
<HintPath>..\..\..\lib\aspnetmvc\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\lib\aspnetmvc\System.Web.WebPages.Deployment.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor">
<HintPath>..\..\..\lib\aspnetmvc\System.Web.WebPages.Razor.dll</HintPath>
</Reference>

View File

@@ -1,27 +1,28 @@
Feature: Addition
In order to prevent security model regressions
As a user with specific permissions
I should to be granted or denied access to various actions
@security
Scenario: Login can be automated
Given I have installed Orchard
And I have a user "bob" with permissions "AccessFrontEnd"
When I go to "users/account/logoff"
Feature: Addition
In order to prevent security model regressions
As a user with specific permissions
I should to be granted or denied access to various actions
@security
Scenario: Login can be automated
Given I have installed Orchard
And I have a user "bob" with permissions "AccessFrontEnd"
When I go to "users/account/logoff"
And I go to "users/account/logon"
And I fill in
| name | value |
| userNameOrEmail | bob |
| password | qwerty123! |
And I hit "Sign In"
And I am redirected
Then I should see "Welcome, <strong>bob</strong>!"
@security
Scenario: Anonymous user can see the home page but not the dashboard
Given I have installed Orchard
And I have a user "bob" with permissions "AccessFrontEnd"
When I sign in as "bob"
Then I should see "this is the homepage of your new site" when I go to "/"
And I should be denied access when I go to "admin"
And I hit "Sign In"
And I am redirected
Then I should see "Welcome"
And I should see "bob"
@security
Scenario: Anonymous user can see the home page but not the dashboard
Given I have installed Orchard
And I have a user "bob" with permissions "AccessFrontEnd"
When I sign in as "bob"
Then I should see "this is the homepage of your new site" when I go to "/"
And I should be denied access when I go to "admin"

View File

@@ -1,7 +1,7 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by SpecFlow (http://www.specflow.org/).
// SpecFlow Version:1.4.0.0
// 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
@@ -14,7 +14,7 @@ namespace Orchard.Specs
using TechTalk.SpecFlow;
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.4.0.0")]
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.5.0.0")]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[NUnit.Framework.TestFixtureAttribute()]
[NUnit.Framework.DescriptionAttribute("Addition")]
@@ -30,8 +30,8 @@ namespace Orchard.Specs
public virtual void FeatureSetup()
{
testRunner = TechTalk.SpecFlow.TestRunnerManager.GetTestRunner();
TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Addition", "In order to prevent security model regressions\nAs a user with specific permission" +
"s\nI should to be granted or denied access to various actions", GenerationTargetLanguage.CSharp, ((string[])(null)));
TechTalk.SpecFlow.FeatureInfo featureInfo = new TechTalk.SpecFlow.FeatureInfo(new System.Globalization.CultureInfo("en-US"), "Addition", "In order to prevent security model regressions\r\nAs a user with specific permissio" +
"ns\r\nI should to be granted or denied access to various actions", GenerationTargetLanguage.CSharp, ((string[])(null)));
testRunner.OnFeatureStart(featureInfo);
}
@@ -87,7 +87,9 @@ this.ScenarioSetup(scenarioInfo);
#line 17
testRunner.And("I am redirected");
#line 18
testRunner.Then("I should see \"Welcome, <strong>bob</strong>!\"");
testRunner.Then("I should see \"Welcome\"");
#line 19
testRunner.And("I should see \"bob\"");
#line hidden
testRunner.CollectScenarioErrors();
}
@@ -99,17 +101,17 @@ this.ScenarioSetup(scenarioInfo);
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Anonymous user can see the home page but not the dashboard", new string[] {
"security"});
#line 21
this.ScenarioSetup(scenarioInfo);
#line 22
testRunner.Given("I have installed Orchard");
this.ScenarioSetup(scenarioInfo);
#line 23
testRunner.And("I have a user \"bob\" with permissions \"AccessFrontEnd\"");
testRunner.Given("I have installed Orchard");
#line 24
testRunner.When("I sign in as \"bob\"");
testRunner.And("I have a user \"bob\" with permissions \"AccessFrontEnd\"");
#line 25
testRunner.Then("I should see \"this is the homepage of your new site\" when I go to \"/\"");
testRunner.When("I sign in as \"bob\"");
#line 26
testRunner.Then("I should see \"this is the homepage of your new site\" when I go to \"/\"");
#line 27
testRunner.And("I should be denied access when I go to \"admin\"");
#line hidden
testRunner.CollectScenarioErrors();

View File

@@ -51,4 +51,4 @@ Scenario: Calling setup on a brand new install
And I hit "Finish Setup"
And I go to "/"
Then I should see "My Site"
And I should see "Welcome, <strong>admin</strong>!"
And I should see "Welcome, <strong><a href="/Users/Account/ChangePassword">admin</a></strong>!"

View File

@@ -1,7 +1,7 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by SpecFlow (http://www.specflow.org/).
// SpecFlow Version:1.4.0.0
// 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
@@ -14,7 +14,7 @@ namespace Orchard.Specs
using TechTalk.SpecFlow;
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.4.0.0")]
[System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "1.5.0.0")]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[NUnit.Framework.TestFixtureAttribute()]
[NUnit.Framework.DescriptionAttribute("Setup")]
@@ -212,7 +212,8 @@ this.ScenarioSetup(scenarioInfo);
#line 53
testRunner.Then("I should see \"My Site\"");
#line 54
testRunner.And("I should see \"Welcome, <strong>admin</strong>!\"");
testRunner.And("I should see \"Welcome, <strong><a href=\"/Users/Account/ChangePassword\">admin</a><" +
"/strong>!\"");
#line hidden
testRunner.CollectScenarioErrors();
}

View File

@@ -11,6 +11,8 @@ using Orchard.Tests.Stubs;
namespace Orchard.Tests.Modules.Packaging {
[TestFixture]
public class PackageBuilderTests : ContainerTestBase {
private const string PackageIdentifier = "Hello.World";
protected override void Register(Autofac.ContainerBuilder builder) {
builder.RegisterType<PackageBuilder>().As<IPackageBuilder>();
builder.RegisterType<InMemoryWebSiteFolder>().As<IWebSiteFolder>()
@@ -27,7 +29,7 @@ namespace Orchard.Tests.Modules.Packaging {
return packageBuilder.BuildPackage(new ExtensionDescriptor {
ExtensionType = DefaultExtensionTypes.Module,
Id = "Hello.World",
Id = PackageIdentifier,
Version = "1.0",
Description = "a",
Author = "b"
@@ -41,7 +43,7 @@ namespace Orchard.Tests.Modules.Packaging {
var package = Package.Open(stream);
Assert.That(package, Is.Not.Null);
Assert.That(package.PackageProperties.Identifier, Is.EqualTo("Orchard.Module.Hello.World"));
Assert.That(package.PackageProperties.Identifier, Is.EqualTo(PackageBuilder.BuildPackageId(PackageIdentifier, DefaultExtensionTypes.Module)));
}
[Test]

View File

@@ -371,6 +371,9 @@
<ItemGroup>
<Content Include="Containers\Views\Parts.Container.Contained.SummaryAdmin.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Shapes\Views\ShapeResult\Display.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -0,0 +1 @@
@Display(Model)

View File

@@ -2,12 +2,14 @@
<div class="user-display">
@if (Request.IsAuthenticated) {
<span class="welcome">@T("Welcome, <strong>{0}</strong>!", WorkContext.CurrentUser.UserName)</span>
<span class="user-actions">
@Html.ActionLink(T("Sign Out").ToString(), "LogOff", new { Controller = "Account", Area = "Orchard.Users", ReturnUrl = Context.Request.RawUrl })
@Html.ActionLink("Dashboard", "Index", new { Area = "Dashboard", Controller = "Admin" })
</span>
<span class="user-actions welcome">
@T("Welcome, <strong>{0}</strong>!", new HtmlString(Html.ActionLink( WorkContext.CurrentUser.UserName, "ChangePassword", new { Controller = "Account", Area = "Orchard.Users" }).ToString()))
</span>
<span class="user-actions">
@Html.ActionLink(T("Sign Out").ToString(), "LogOff", new { Controller = "Account", Area = "Orchard.Users", ReturnUrl = Context.Request.RawUrl })
@Html.ActionLink("Dashboard", "Index", new { Area = "Dashboard", Controller = "Admin" })
</span>
} else {
<span class="user-actions">@Html.ActionLink(T("Sign In").ToString(), "LogOn", new { Controller = "Account", Area = "Orchard.Users", ReturnUrl = Context.Request.RawUrl })</span>
<span class="user-actions">@Html.ActionLink(T("Sign In").ToString(), "LogOn", new { Controller = "Account", Area = "Orchard.Users", ReturnUrl = Context.Request.RawUrl })</span>
}
</div>

View File

@@ -1,8 +1,11 @@
@model Orchard.ContentTypes.ViewModels.EditTypePartViewModel
@using Orchard.Core.Contents.Settings;
<fieldset class="manage-part" itemscope="itemscope" itemid="@Model.PartDefinition.Name" itemtype="http://orchardproject.net/data/ContentTypePart">
<h3 itemprop="Name">@Model.PartDefinition.DisplayName</h3>
<div class="manage">
@Html.ActionLink(T("Remove").Text, "RemovePartFrom", new { area = "Orchard.ContentTypes", id = Model.Type.Name, Model.PartDefinition.Name }, new { itemprop = "RemoveUrl UnsafeUrl" }) @* <- some experimentation *@
@if (Model.PartDefinition.Settings.GetModel<ContentPartSettings>().Attachable) {
@Html.ActionLink(T("Remove").Text, "RemovePartFrom", new { area = "Orchard.ContentTypes", id = Model.Type.Name, Model.PartDefinition.Name }, new { itemprop = "RemoveUrl UnsafeUrl" });
}
</div>
<div class="details">@Html.EditorFor(m => m.PartDefinition.Fields, "TypePartFields", "PartDefinition")
@if (Model.Templates.Any()) {

View File

@@ -84,25 +84,25 @@ namespace Orchard.Experimental.Controllers {
public ActionResult UsingShapes() {
ViewModel.Page = Shape.Page()
ViewBag.Page = Shape.Page()
.Main(Shape.Zone(typeof (Array), Name: "Main"))
.Messages(Shape.Zone(typeof (Array), Name: "Messages"))
.Sidebar(Shape.Zone(typeof (Array), Name: "Sidebar"));
//ViewModel.Page.Add("Messages:5", New.Message(Content: T("This is a test"), Severity: "Really bad!!!"));
ViewModel.Page.Messages.Add(
ViewBag.Page.Messages.Add(
Shape.Message(Content: T("This is a test"), Severity: "Really bad!!!"));
ViewModel.Page.Sidebar.Add(
ViewBag.Page.Sidebar.Add(
Shape.Link(Url: "http://orchard.codeplex.com", Content: Shape.Image(Url: "http://orchardproject.net/Content/images/orchardLogo.jpg").Attributes(new { @class = "bigredborderfromabadclassname" })));
var model = Shape.Message(
Content: Shape.Explosion(Height: 100, Width: 200),
Severity: "Meh");
ViewModel.Page.Messages.Add(new HtmlString("<hr/>abuse<hr/>"));
ViewModel.Page.Messages.Add("<hr/>encoded<hr/>");
ViewBag.Page.Messages.Add(new HtmlString("<hr/>abuse<hr/>"));
ViewBag.Page.Messages.Add("<hr/>encoded<hr/>");
return View(model);
}

View File

@@ -103,8 +103,7 @@ namespace Orchard.Indexing.Services {
? _repository.Fetch(x => true).ToArray()
: _repository.Fetch(x => x.CreatedUtc >= lastIndexUtc).ToArray(); // CreatedUtc and lastIndexUtc might be equal if a content item is created in a background task
// nothing to do ?
// nothing to do ?)))
if (taskRecords.Length + updateIndexDocuments.Count == 0) {
Logger.Information("Index update requested, nothing to do");
return;
@@ -140,7 +139,7 @@ namespace Orchard.Indexing.Services {
try {
var documentIndex = _indexProvider.New(task.ContentItem.Id);
_contentManager.Index(task.ContentItem, documentIndex);
if (documentIndex.IsDirty) {
if (!addedContentItemIds.Contains(task.ContentItem.Id.ToString()) && documentIndex.IsDirty) {
updateIndexDocuments.Add(documentIndex);
}

View File

@@ -58,16 +58,18 @@ namespace Orchard.Modules.Services {
public void EnableFeatures(IEnumerable<string> features, bool force) {
var shellDescriptor = _shellDescriptorManager.GetShellDescriptor();
var enabledFeatures = shellDescriptor.Features.ToList();
var availableFeatures = GetAvailableFeatures().ToList();
var featuresToEnable =
features.Select(s => EnableFeature(s, GetAvailableFeatures(), force)).
SelectMany(ies => ies.Select(s => s));
var featuresToEnable = features
.Select(s => EnableFeature(s, availableFeatures, force)).ToList()
.SelectMany(ies => ies.Select(s => s));
if (featuresToEnable.Count() == 0)
return;
foreach (var featureToEnable in featuresToEnable) {
enabledFeatures.Add(new ShellFeature {Name = featureToEnable});
var feature = featureToEnable;
enabledFeatures.Add(new ShellFeature { Name = feature });
Services.Notifier.Information(T("{0} was enabled", featureToEnable));
}
@@ -84,9 +86,9 @@ namespace Orchard.Modules.Services {
var enabledFeatures = shellDescriptor.Features.ToList();
var availableFeatures = GetAvailableFeatures().ToList();
var featuresToDisable =
features.Select(s => DisableFeature(s, availableFeatures, force)).SelectMany(
ies => ies.Select(s => s));
var featuresToDisable = features
.Select(s => DisableFeature(s, availableFeatures, force)).ToList()
.SelectMany(ies => ies.Select(s => s));
if (featuresToDisable.Count() == 0)
return;

View File

@@ -25,7 +25,10 @@
<ul class="pageStatus" style="color:#666; margin:.6em 0 0 0;">
<li>@T("Features: {0}", MvcHtmlString.Create(string.Join(", ", module.Features.Select(f => Html.Link(string.IsNullOrEmpty(f.Name) ? f.Id : f.Name, string.Format("{0}#{1}", Url.Action("features", new { area = "Orchard.Modules" }), f.Id.AsFeatureId(n => T(n)))).ToString()).OrderBy(s => s).ToArray())))</li>
<li>&nbsp;&#124;&nbsp;@T("Author: {0}", !string.IsNullOrEmpty(module.Author) ? module.Author : T("Unknown").ToString())</li>
<li>&nbsp;&#124;&nbsp;@T("Website: {0}", !string.IsNullOrEmpty(module.WebSite) ? module.WebSite : "http://orchardproject.net")</li>
<li>&nbsp;&#124;&nbsp;@T("Website: ")
@if (!string.IsNullOrEmpty(module.WebSite)) { <a href="@module.WebSite">@module.WebSite</a> }
else { @T("Unknown").ToString() }
</li>
</ul>
</div>
</div>

View File

@@ -4,7 +4,6 @@ using System.Web;
using System.Web.Hosting;
using Orchard.Commands;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
using Orchard.Packaging.Services;
using Orchard.UI.Notify;
@@ -39,11 +38,10 @@ namespace Orchard.Packaging.Commands {
}
// append "Orchard.[ExtensionType]" to prevent conflicts with other packages (e.g, TinyMce, jQuery, ...)
string extensionPrefix = DefaultExtensionTypes.IsTheme(packageData.ExtensionType) ?
PackagingSourceManager.ThemesPrefix :
PackagingSourceManager.ModulesPrefix;
var filename = string.Format("{0}{1}.{2}.nupkg", extensionPrefix, packageData.ExtensionName, packageData.ExtensionVersion);
var filename = string.Format("{0}{1}.{2}.nupkg",
PackagingSourceManager.GetExtensionPrefix(packageData.ExtensionType),
packageData.ExtensionName,
packageData.ExtensionVersion);
if ( !Directory.Exists(path) ) {
Directory.CreateDirectory(path);
@@ -77,7 +75,11 @@ namespace Orchard.Packaging.Commands {
}
}
[CommandHelp("package uninstall <packageId> \r\n\t" + "Uninstall a module or a theme.")]
[CommandHelp(@"package uninstall <packageId>
Uninstall a module or a theme.
The <packageId> should take the format Orchard.[Module|Theme].<extensionName>.
For example, ""package uninstall Orchard.Module.SampleModule"" will uninstall the Module under the ""~/Modules/SampleModule"" directory and
""package uninstall Orchard.Theme.SampleTheme"" will uninstall the Theme under the ""~/Themes/SampleTheme"" directory.")]
[CommandName("package uninstall")]
public void UninstallPackage(string packageId) {
try {

View File

@@ -6,8 +6,10 @@ using System.Web.Hosting;
using System.Web.Mvc;
using System.Xml.Linq;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
using Orchard.Localization;
using Orchard.Logging;
using Orchard.Packaging.Models;
using Orchard.Packaging.Services;
using Orchard.Packaging.ViewModels;
using Orchard.Security;
@@ -113,7 +115,15 @@ namespace Orchard.Packaging.Controllers {
}
public ActionResult Modules(int? sourceId) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list modules")))
return ListExtensions(sourceId, DefaultExtensionTypes.Module, "Modules", source => _packagingSourceManager.GetModuleList(source).ToArray());
}
public ActionResult Themes(int? sourceId) {
return ListExtensions(sourceId, DefaultExtensionTypes.Theme, "Themes", source => _packagingSourceManager.GetThemeList(source).ToArray());
}
protected ActionResult ListExtensions(int? sourceId, string extensionType, string returnView, Func<PackagingSource, PackagingEntry[]> getList) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list {0}", extensionType)))
return new HttpUnauthorizedResult();
var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault();
@@ -126,35 +136,16 @@ namespace Orchard.Packaging.Controllers {
IEnumerable<PackagingEntry> extensions = null;
foreach (var source in sources) {
try {
var sourceExtensions = _packagingSourceManager.GetModuleList(source).ToArray();
var sourceExtensions = getList(source);
extensions = extensions == null ? sourceExtensions : extensions.Concat(sourceExtensions);
}
catch (Exception ex) {
} catch (Exception ex) {
Logger.Error(ex, "Error loading extensions from gallery source '{0}'. {1}.", source.FeedTitle, ex.Message);
_notifier.Error(T("Error loading extensions from gallery source '{0}'. {1}.", source.FeedTitle, ex.Message));
}
}
return View("Modules", new PackagingExtensionsViewModel {
Extensions = extensions ?? new PackagingEntry[] {},
Sources = _packagingSourceManager.GetSources().OrderBy(s => s.FeedTitle),
SelectedSource = selectedSource
});
}
public ActionResult Themes(int? sourceId) {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to list themes")))
return new HttpUnauthorizedResult();
var selectedSource = _packagingSourceManager.GetSources().Where(s => s.Id == sourceId).FirstOrDefault();
var sources = selectedSource != null
? new[] { selectedSource }
: _packagingSourceManager.GetSources()
;
return View("Themes", new PackagingExtensionsViewModel {
Extensions = sources.SelectMany(source => _packagingSourceManager.GetThemeList(source)),
return View(returnView, new PackagingExtensionsViewModel {
Extensions = extensions ?? new PackagingEntry[] { },
Sources = _packagingSourceManager.GetSources().OrderBy(s => s.FeedTitle),
SelectedSource = selectedSource
});

View File

@@ -5,6 +5,7 @@ using System.Web.Hosting;
using System.Web.Mvc;
using NuGet;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
using Orchard.FileSystems.AppData;
using Orchard.Localization;
using Orchard.Mvc.Extensions;
@@ -14,6 +15,7 @@ using Orchard.Themes;
using Orchard.UI.Admin;
using Orchard.UI.Notify;
using IPackageManager = Orchard.Packaging.Services.IPackageManager;
using PackageBuilder = Orchard.Packaging.Services.PackageBuilder;
namespace Orchard.Packaging.Controllers {
[OrchardFeature("PackagingServices")]
@@ -60,7 +62,7 @@ namespace Orchard.Packaging.Controllers {
if (!Services.Authorizer.Authorize(StandardPermissions.SiteOwner, T("Not authorized to remove themes")))
return new HttpUnauthorizedResult();
return UninstallPackage(PackagingSourceManager.ThemesPrefix + themeId, returnUrl, retryUrl);
return UninstallPackage(PackageBuilder.BuildPackageId(themeId, DefaultExtensionTypes.Theme), returnUrl, retryUrl);
}
public ActionResult AddModule(string returnUrl) {

View File

@@ -20,7 +20,7 @@ namespace Orchard.Packaging {
public void Installed(Feature feature) {
if (feature.Descriptor.Id == "Gallery") {
_packagingSourceManager.AddSource("Orchard Extensions Gallery", "http://orchardproject.net/gallery09/server/feedservice.svc");
_packagingSourceManager.AddSource("Orchard Extensions Gallery", "http://orchardproject.net/gallery09/server/FeedService.svc");
}
}

View File

@@ -93,6 +93,9 @@
<Compile Include="ViewModels\PackagingSourcesViewModel.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\Images\moduleDefaultIcon.png" />
<Content Include="Content\Images\packageDefaultIcon.png" />
<Content Include="Content\Images\themeDefaultIcon.png" />
<Content Include="Module.txt" />
<Content Include="Service References\GalleryServer\Reference.datasvcmap">
<Generator>DataServiceClientGenerator</Generator>

View File

@@ -39,7 +39,7 @@ namespace Orchard.Packaging.Services {
public override IQueryable<IPackage> GetPackages() {
IEnumerable<IPackage> packages = from extension in _extensionManager.AvailableExtensions()
let id = "Orchard." + extension.ExtensionType + "." + extension.Id
let id = PackageBuilder.BuildPackageId(extension.Id, extension.ExtensionType)
let version = Version.Parse(extension.Version)
let package = SourceRepository.FindPackage(id, version)
where package != null

View File

@@ -20,6 +20,7 @@ namespace Orchard.Packaging.Services {
private static readonly string[] _ignoredThemeExtensions = new[] {
"obj", "pdb", "exclude"
};
private static readonly string[] _ignoredThemePaths = new[] {
"/obj/"
};
@@ -61,13 +62,13 @@ namespace Orchard.Packaging.Services {
return context.Stream;
}
private static void SetCoreProperties(CreateContext context, ExtensionDescriptor extensionDescriptor) {
string idPrefix = DefaultExtensionTypes.IsTheme(extensionDescriptor.ExtensionType) ?
PackagingSourceManager.ThemesPrefix :
PackagingSourceManager.ModulesPrefix;
context.Builder.Id = idPrefix + extensionDescriptor.Id;
public static string BuildPackageId(string extensionName, string extensionType) {
return PackagingSourceManager.GetExtensionPrefix(extensionType) + extensionName;
}
private static void SetCoreProperties(CreateContext context, ExtensionDescriptor extensionDescriptor) {
context.Builder.Id = BuildPackageId(extensionDescriptor.Id, extensionDescriptor.ExtensionType);
context.Builder.Version = new Version(extensionDescriptor.Version);
context.Builder.Title = extensionDescriptor.Name ?? extensionDescriptor.Id;
context.Builder.Description = extensionDescriptor.Description;

View File

@@ -93,19 +93,33 @@ namespace Orchard.Packaging.Services {
return new PackageInfo {
ExtensionName = package.Title ?? package.Id,
ExtensionVersion = package.Version.ToString(),
ExtensionType = package.Id.StartsWith(PackagingSourceManager.ThemesPrefix) ? DefaultExtensionTypes.Theme : DefaultExtensionTypes.Module,
ExtensionType = package.Id.StartsWith(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Theme)) ? DefaultExtensionTypes.Theme : DefaultExtensionTypes.Module,
ExtensionPath = applicationPath
};
}
public void Uninstall(string packageId, string applicationPath) {
// this logger is used to render NuGet's log on the notifier
var logger = new NugetLogger(_notifier);
string solutionPath;
string extensionFullPath = string.Empty;
if (packageId.StartsWith(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Theme))) {
extensionFullPath = HostingEnvironment.MapPath("~/Themes/" + packageId.Substring(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Theme).Length));
} else if (packageId.StartsWith(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Module))) {
extensionFullPath = HostingEnvironment.MapPath("~/Modules/" + packageId.Substring(PackagingSourceManager.GetExtensionPrefix(DefaultExtensionTypes.Module).Length));
}
if (string.IsNullOrEmpty(extensionFullPath) ||
!Directory.Exists(extensionFullPath)) {
throw new OrchardException(T("Package not found: {0}", packageId));
}
// if we can access the parent directory, and the solution is inside, NuGet-uninstall the package here
if (TryGetSolutionPath(applicationPath, out solutionPath)) {
// this logger is used to render NuGet's log on the notifier
var logger = new NugetLogger(_notifier);
var installedPackagesPath = Path.Combine(solutionPath, PackagesPath);
var sourcePackageRepository = new LocalPackageRepository(installedPackagesPath);
@@ -139,19 +153,10 @@ namespace Orchard.Packaging.Services {
}
}
// Make sure folder is deleted (themes scenario where there is no project)
string extensionPath = packageId.StartsWith(PackagingSourceManager.ThemesPrefix)
? "~/Themes/" + packageId.Substring(PackagingSourceManager.ThemesPrefix.Length)
: "~/Modules/" + packageId.Substring(PackagingSourceManager.ThemesPrefix.Length);
string extensionFullPath = HostingEnvironment.MapPath(extensionPath);
if (Directory.Exists(extensionFullPath)) {
// If the package was not installed through nuget we still need to try to uninstall it by removing its directory
if(Directory.Exists(extensionFullPath)) {
Directory.Delete(extensionFullPath, true);
}
else {
throw new OrchardException(T("Package not found: ", packageId));
}
}
private static bool TryGetSolutionPath(string applicationPath, out string parentPath) {

View File

@@ -12,5 +12,9 @@ namespace Orchard.Packaging.Services {
public DateTime LastUpdated { get; set; }
public string Authors { get; set; }
public string Description { get; set; }
public string FirstScreenshot { get; set; }
public string IconUrl { get; set; }
public double Rating { get; set; }
public int RatingsCount { get; set; }
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NuGet;
using Orchard.Data;
using Orchard.Environment.Extensions;
using Orchard.Environment.Extensions.Models;
@@ -12,8 +11,9 @@ using Orchard.Packaging.Models;
namespace Orchard.Packaging.Services {
[OrchardFeature("Gallery")]
public class PackagingSourceManager : IPackagingSourceManager {
public const string ThemesPrefix = "Orchard.Themes.";
public const string ModulesPrefix = "Orchard.Modules.";
public static string GetExtensionPrefix(string extensionType) {
return string.Format("Orchard.{0}.", extensionType);
}
private readonly IRepository<PackagingSource> _packagingSourceRecordRepository;
@@ -63,19 +63,25 @@ namespace Orchard.Packaging.Services {
}
private static PackagingEntry CreatePackageEntry(PublishedPackage package, PackagingSource source, Uri downloadUri) {
PublishedScreenshot firstScreenshot = package.Screenshots.FirstOrDefault();
return new PackagingEntry {
Title = String.IsNullOrWhiteSpace(package.Title) ? package.Id : package.Title,
Title = string.IsNullOrWhiteSpace(package.Title) ? package.Id : package.Title,
PackageId = package.Id,
PackageStreamUri = downloadUri.ToString(),
ProjectUrl = package.ProjectUrl,
Source = source,
Version = package.Version ?? String.Empty,
Version = package.Version ?? string.Empty,
Description = package.Description,
Authors = package.Authors,
LastUpdated = package.LastUpdated
LastUpdated = package.LastUpdated,
IconUrl = package.IconUrl,
FirstScreenshot = firstScreenshot != null ? firstScreenshot.ScreenshotUri : string.Empty,
Rating = package.Rating,
RatingsCount = package.RatingsCount
};
}
#endregion
#endregion
}
}

View File

@@ -1,17 +1,22 @@
.moduleName {
.extensionName {
float:left;
}
}
.contentItems .related {
padding:1.2em 0.4em 0.5em
padding: 1.2em 0.4em 0.5em
}
.contentItems .properties {
float:none;
clear:both;
float:left;
}
.contentItems .pageStatus {
margin:.8em 0;
color:#666;
}
.thumbnail {
float: left;
padding: 1.2em 1.2em 0.5em 0em;
width: 10%;
}
.extensionDetails {
float: left;
width: 85%;
}

View File

@@ -22,23 +22,38 @@
<ul class="contentItems">
@foreach (var item in Model.Extensions) {
<li>
<div class="moduleName">
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
@{
string iconUrl = @item.IconUrl;
if (string.IsNullOrWhiteSpace(iconUrl)) {
iconUrl = Href("../../Content/Images/ModuleDefaultIcon.png");
}
}
<img src="@iconUrl" class="thumbnail"/>
<div class="extensionDetails">
<div class="extensionName">
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
</div>
<div class="related">
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"packageId", item.PackageId}, {"version", item.Version}, {"sourceId", item.Source.Id}, {"redirectTo", "Modules"}})@T(" | ")
<a href="@item.PackageStreamUri">@T("Download")</a>
</div>
<div class="properties">
<p>@(item.Description == null ? T("(No description").Text : item.Description)</p>
<ul class="pageStatus">
<li>@T("Last Updated: {0}", DateTime.Now.ToLocalTime())</li>
<li>&nbsp;&#124;&nbsp;@T("Author: {0}", !string.IsNullOrEmpty(item.Authors) ? item.Authors : T("Unknown").ToString())</li>
<li>&nbsp;&#124;&nbsp;@T("Rating: {0}", item.Rating)</li>
<li>&nbsp;&#124;&nbsp;@T("Ratings Count: {0}", item.RatingsCount)</li>
<li>&nbsp;&#124;&nbsp;@T("Website: ")
@if(!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> }
else { @T("Unknown").ToString() }
</li>
</ul>
</div>
</div>
<div class="related">
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"packageId", item.PackageId}, {"version", item.Version}, {"sourceId", item.Source.Id}, {"redirectTo", "Modules"}})@T(" | ")
<a href="@item.PackageStreamUri">@T("Download")</a>
</div>
<div class="properties">
<p>@(item.Description == null ? T("(No description").Text : item.Description)</p>
<ul class="pageStatus">
<li>@T("Last Updated: {0}", DateTime.Now.ToLocalTime())</li>
<li>&nbsp;&#124;&nbsp;@T("Author: {0}", item.Authors)</li>
<li>&nbsp;&#124;&nbsp;@T("Project Url: ")<a href="@item.ProjectUrl">@item.ProjectUrl</a></li>
</ul>
</div>
</li>}
</ul>
}

View File

@@ -22,23 +22,41 @@
<ul class="contentItems">
@foreach (var item in Model.Extensions) {
<li>
<div class="moduleName">
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
@{
string iconUrl = @item.IconUrl;
if (!string.IsNullOrWhiteSpace(@item.FirstScreenshot)) {
iconUrl = Href(@item.FirstScreenshot);
}
else if (string.IsNullOrWhiteSpace(iconUrl)) {
iconUrl = Href("../../Content/Images/imagePlaceholder.png");
}
}
<img src="@iconUrl" class="thumbnail" />
<div class="extensionDetails">
<div class="extensionName">
<h2>@item.Title<span> - @T("Version: {0}", item.Version)</span></h2>
</div>
<div class="related">
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"packageId", item.PackageId}, {"version", item.Version}, {"sourceId", item.Source.Id}, {"redirectTo", "Themes"}})@T(" | ")
<a href="@item.PackageStreamUri">@T("Download")</a>
</div>
<div class="properties">
<p>@(item.Description == null ? T("(No description").Text : item.Description)</p>
<ul class="pageStatus">
<li>@T("Last Updated: {0}", DateTime.Now.ToLocalTime())</li>
<li>&nbsp;&#124;&nbsp;@T("Author: {0}", !string.IsNullOrEmpty(item.Authors) ? item.Authors : T("Unknown").ToString())</li>
<li>&nbsp;&#124;&nbsp;@T("Rating: {0}", item.Rating)</li>
<li>&nbsp;&#124;&nbsp;@T("Ratings Count: {0}", item.RatingsCount)</li>
<li>&nbsp;&#124;&nbsp;@T("Website: ")
@if(!string.IsNullOrEmpty(item.ProjectUrl)) { <a href="@item.ProjectUrl">@item.ProjectUrl</a> }
else { @T("Unknown").ToString() }
</li>
</ul>
</div>
</div>
<div class="related">
@Html.ActionLink(T("Install").ToString(), "Install", new RouteValueDictionary {{"packageId", item.PackageId}, {"version", item.Version}, {"sourceId", item.Source.Id}, {"redirectTo", "Themes"}})@T(" | ")
<a href="@item.PackageStreamUri">@T("Download")</a>
</div>
<div class="properties">
<p>@(item.Description == null ? T("(No description").Text : item.Description)</p>
<ul class="pageStatus">
<li>@T("Last Updated: {0}", DateTime.Now.ToLocalTime())</li>
<li>&nbsp;&#124;&nbsp;@T("Author: {0}", item.Authors)</li>
<li>&nbsp;&#124;&nbsp;@T("Project Url: ")<a href="@item.ProjectUrl">@item.ProjectUrl</a></li>
</ul>
</div>
</li>}
</ul>
}

View File

@@ -9,7 +9,7 @@
<h1>@Html.TitleForPage(T("Manage Tags").ToString()) </h1>
@Html.ValidationSummary()
<div class="manage">
@Display.EditorTemplate(TemplateName: "Parts/CreateTag", Model: View.CreateTag != null ? View.CreateTag : new TagsAdminCreateViewModel())
@Display.EditorTemplate(TemplateName: "Parts/CreateTag", Model: ViewData["CreateTag"] != null ? ViewData["CreateTag"] : new TagsAdminCreateViewModel())
</div>
@using(Html.BeginFormAntiForgeryPost()) {
<fieldset class="bulk-actions">

View File

@@ -5,11 +5,11 @@ using System.Security.Principal;
using System.Web.Mvc;
using System.Web.Security;
using Orchard.Logging;
using Orchard.Mvc;
using Orchard.Mvc.Extensions;
using Orchard.Security;
using Orchard.Themes;
using Orchard.Users.Services;
using Orchard.Users.ViewModels;
using Orchard.ContentManagement;
using Orchard.Users.Models;
using Orchard.UI.Notify;
@@ -44,7 +44,8 @@ namespace Orchard.Users.Controllers {
if (currentUser == null) {
Logger.Information("Access denied to anonymous request on {0}", returnUrl);
return View("LogOn", new LogOnViewModel {Title = "Access Denied"});
var shape = _orchardServices.New.LogOn().Title(T("Access Denied").Text);
return new ShapeResult(shape);
}
//TODO: (erikpo) Add a setting for whether or not to log access denieds since these can fill up a database pretty fast from bots on a high traffic site
@@ -57,7 +58,8 @@ namespace Orchard.Users.Controllers {
if (_authenticationService.GetAuthenticatedUser() != null)
return Redirect("~/");
return View(new LogOnViewModel { Title = T("Log On").Text });
var shape = _orchardServices.New.LogOn().Title(T("Log On").Text);
return new ShapeResult(shape);
}
[HttpPost]
@@ -66,7 +68,8 @@ namespace Orchard.Users.Controllers {
public ActionResult LogOn(string userNameOrEmail, string password, string returnUrl) {
var user = ValidateLogOn(userNameOrEmail, password);
if (!ModelState.IsValid) {
return View(new LogOnViewModel { Title = T("Log On").Text });
var shape = _orchardServices.New.LogOn().Title(T("Log On").Text);
return new ShapeResult(shape);
}
_authenticationService.SignIn(user, false);
@@ -157,7 +160,7 @@ namespace Orchard.Users.Controllers {
return View();
}
_userService.SendLostPasswordEmail(username, nonce => Url.AbsoluteAction(() => Url.Action("ValidateLostPassword", "Account", new { Area = "Orchard.Users", nonce = nonce })));
_userService.SendLostPasswordEmail(username, nonce => Url.AbsoluteAction(() => Url.Action("LostPassword", "Account", new { Area = "Orchard.Users", nonce = nonce })));
_orchardServices.Notifier.Information(T("Check your e-mail for the confirmation link."));
@@ -259,7 +262,6 @@ namespace Orchard.Users.Controllers {
var user = _userService.ValidateChallenge(nonce);
if ( user != null ) {
_authenticationService.SignIn(user, false /* createPersistentCookie */);
return RedirectToAction("ChallengeEmailSuccess");
}

View File

@@ -31,30 +31,42 @@ namespace Orchard.Users.Handlers {
if ( recipient == null )
return;
if ( context.Type == MessageTypes.Moderation ) {
context.MailMessage.Subject = T("User needs moderation").Text;
context.MailMessage.Body = T("The following user account needs to be moderated: {0}", recipient.UserName).Text;
switch (context.Type) {
case MessageTypes.Moderation:
context.MailMessage.Subject = T("New account").Text;
context.MailMessage.Body =
T("The user <b>{0}</b> with email <b>{1}</b> has requested a new account. This user won't be able to log while his account has not been approved.",
context.Properties["UserName"], context.Properties["Email"]).Text;
FormatEmailBody(context);
context.MessagePrepared = true;
break;
case MessageTypes.Validation:
var registeredWebsite = _siteService.GetSiteSettings().As<RegistrationSettingsPart>().ValidateEmailRegisteredWebsite;
var contactEmail = _siteService.GetSiteSettings().As<RegistrationSettingsPart>().ValidateEmailContactEMail;
context.MailMessage.Subject = T("Verification E-Mail").Text;
context.MailMessage.Body =
T("Thank you for registering with {0}.<br/><br/><br/><b>Final Step</b><br/>To verify that you own this e-mail address, please click the following link:<br/><a href=\"{1}\">{1}</a><br/><br/><b>Troubleshooting:</b><br/>If clicking on the link above does not work, try the following:<br/><br/>Select and copy the entire link.<br/>Open a browser window and paste the link in the address bar.<br/>Click <b>Go</b> or, on your keyboard, press <b>Enter</b> or <b>Return</b>.",
registeredWebsite, context.Properties["ChallengeUrl"]).Text;
if (!String.IsNullOrWhiteSpace(contactEmail)) {
context.MailMessage.Body +=
T("<br/><br/>If you continue to have access problems or want to report other issues, please <a href=\"mailto:{0}\">Contact Us</a>.",
contactEmail).Text;
}
FormatEmailBody(context);
context.MessagePrepared = true;
break;
case MessageTypes.LostPassword:
context.MailMessage.Subject = T("Lost password").Text;
context.MailMessage.Body =
T("Dear {0}, please <a href=\"{1}\">click here</a> to change your password.", recipient.UserName,
context.Properties["LostPasswordUrl"]).Text;
FormatEmailBody(context);
context.MessagePrepared = true;
break;
}
if (context.Type == MessageTypes.Validation) {
var registeredWebsite = _siteService.GetSiteSettings().As<RegistrationSettingsPart>().ValidateEmailRegisteredWebsite;
var contactEmail = _siteService.GetSiteSettings().As<RegistrationSettingsPart>().ValidateEmailContactEMail;
context.MailMessage.Subject = T("Verification E-Mail").Text;
context.MailMessage.Body =
T("Thank you for registering with {0}.<br/><br/><br/><b>Final Step</b><br/>To verify that you own this e-mail address, please click the following link:<br/><a href=\"{1}\">{1}</a><br/><br/><b>Troubleshooting:</b><br/>If clicking on the link above does not work, try the following:<br/><br/>Select and copy the entire link.<br/>Open a browser window and paste the link in the address bar.<br/>Click <b>Go</b> or, on your keyboard, press <b>Enter</b> or <b>Return</b>.", registeredWebsite, context.Properties["ChallengeUrl"]).Text;
if (!String.IsNullOrWhiteSpace(contactEmail)) {
context.MailMessage.Body += T("<br/><br/>If you continue to have access problems or want to report other issues, please <a href=\"mailto:{0}\">Contact Us</a>.", contactEmail).Text;
}
}
if (context.Type == MessageTypes.LostPassword) {
context.MailMessage.Subject = T("Lost password").Text;
context.MailMessage.Body = T("Dear {0}, please <a href=\"{1}\">click here</a> to change your password.", recipient.UserName, context.Properties["LostPasswordUrl"]).Text;
}
FormatEmailBody(context);
context.MessagePrepared = true;
}
private static void FormatEmailBody(MessageContext context) {

View File

@@ -75,7 +75,6 @@
<Compile Include="AdminMenu.cs" />
<Compile Include="Services\MissingSettingsBanner.cs" />
<Compile Include="Services\UserService.cs" />
<Compile Include="ViewModels\LogOnViewModel.cs" />
<Compile Include="ViewModels\UserCreateViewModel.cs" />
<Compile Include="ViewModels\UserEditViewModel.cs" />
<Compile Include="ViewModels\UsersIndexViewModel.cs" />
@@ -90,7 +89,6 @@
<Content Include="Views\Account\ChallengeEmailSuccess.cshtml" />
<Content Include="Views\Account\ChallengeEmailSent.cshtml" />
<Content Include="Views\Account\ChallengeEmailFail.cshtml" />
<Content Include="Views\Account\LogOn.cshtml" />
<Content Include="Views\Account\Register.cshtml" />
<Content Include="Views\Admin\Edit.cshtml" />
<Content Include="Views\Admin\Create.cshtml" />
@@ -129,6 +127,9 @@
<ItemGroup>
<Content Include="Views\Account\LostPassword.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\LogOn.cshtml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.

View File

@@ -89,7 +89,7 @@ namespace Orchard.Users.Services {
}
var recipient = GetUser(userName);
if (recipient != null)
_messageManager.Send(recipient.ContentItem.Record, MessageTypes.Moderation, "email");
_messageManager.Send(recipient.ContentItem.Record, MessageTypes.Moderation, "email" , new Dictionary<string, string> { { "UserName", createUserParams.Username}, { "Email" , createUserParams.Email } });
}
}

View File

@@ -1,5 +0,0 @@
namespace Orchard.Users.ViewModels {
public class LogOnViewModel {
public string Title { get; set; }
}
}

View File

@@ -1,12 +1,11 @@
@model Orchard.Users.ViewModels.LogOnViewModel
@using Orchard.ContentManagement;
@using Orchard.ContentManagement;
@{
var userCanRegister = @WorkContext.CurrentSite.As<Orchard.Users.Models.RegistrationSettingsPart>().UsersCanRegister;
var enableLostPassword = @WorkContext.CurrentSite.As<Orchard.Users.Models.RegistrationSettingsPart>().EnableLostPassword;
}
<h1 class="page-title">@Html.TitleForPage(Model.Title)</h1>
<h1 class="page-title">@Html.TitleForPage((string)Model.Title)</h1>
<p>
@T("Please enter your username and password.")
@if(userCanRegister) { @Html.ActionLink(T("Register").Text, "Register") @T(" if you don't have an account.") }

View File

@@ -100,6 +100,10 @@
<HintPath>..\..\lib\aspnetmvc\System.Web.WebPages.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\aspnetmvc\System.Web.WebPages.Deployment.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\aspnetmvc\System.Web.WebPages.Razor.dll</HintPath>

View File

@@ -217,7 +217,7 @@ input[type="submit"]:focus::-moz-focus-inner, button:focus::-moz-focus-inner, .b
}
#throbber .curtain
{
position:absolute;
position:fixed;
left:0;
top:0;
width:100%;
@@ -239,7 +239,6 @@ input[type="submit"]:focus::-moz-focus-inner, button:focus::-moz-focus-inner, .b
padding:250px;
color:White;
}
.message, .validation-summary-errors {
margin:10px 0 4px 0;
padding:4px;

View File

@@ -171,7 +171,8 @@ namespace Orchard.Environment.State {
}
// raise install and enabled states in order
foreach (var entry in allEntries.Where(entry => IsRising(entry.FeatureState))) {
foreach (var entry in allEntries.Reverse().Where(entry => IsRising(entry.FeatureState)))
{
if (entry.FeatureState.InstallState == ShellFeatureState.State.Rising) {
Logger.Information("Installing feature '{0}'", entry.Feature.Descriptor.Id);
_featureEvents.Installing(entry.Feature);

View File

@@ -0,0 +1,10 @@
using System.Web.Mvc;
namespace Orchard.Mvc {
public class ShapeResult : ViewResult {
public ShapeResult(dynamic shape) {
ViewData.Model = shape;
ViewName = "~/Core/Shapes/Views/ShapeResult/Display.cshtml";
}
}
}

View File

@@ -139,6 +139,10 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\aspnetmvc\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\lib\aspnetmvc\System.Web.WebPages.Deployment.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor">
<HintPath>..\..\lib\aspnetmvc\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
@@ -181,6 +185,7 @@
<Compile Include="Messaging\Services\DefaultMessageManager.cs" />
<Compile Include="Mvc\Extensions\ControllerExtensions.cs" />
<Compile Include="Mvc\IOrchardViewPage.cs" />
<Compile Include="Mvc\ShapeResult.cs" />
<Compile Include="Mvc\Spooling\HtmlStringWriter.cs" />
<Compile Include="Mvc\ViewEngines\Razor\IRazorCompilationEvents.cs" />
<Compile Include="Security\IEncryptionService.cs" />