mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
Compare commits
72 Commits
feature/sq
...
feature/we
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
248cc7ecde | ||
|
|
bb41f1f559 | ||
|
|
5903f75665 | ||
|
|
46182edc5d | ||
|
|
accd4196dc | ||
|
|
d3d85f3519 | ||
|
|
6e90f704f8 | ||
|
|
497b782a6a | ||
|
|
bc935f18b3 | ||
|
|
12a51ea7af | ||
|
|
f0b1639143 | ||
|
|
9bb95efaaa | ||
|
|
e6c042d1a0 | ||
|
|
df583ea571 | ||
|
|
adbab55ffc | ||
|
|
20fbd99658 | ||
|
|
d9a0e040c1 | ||
|
|
4aaf4d34d0 | ||
|
|
7143792c0e | ||
|
|
4214329a1f | ||
|
|
921b2472f1 | ||
|
|
9e9e19c439 | ||
|
|
f3595881fe | ||
|
|
ba36eae848 | ||
|
|
0bf76dc7ac | ||
|
|
66ff5d36e9 | ||
|
|
749ff5dc72 | ||
|
|
85c4a99c13 | ||
|
|
a3fe3592c6 | ||
|
|
a2c31a1e5c | ||
|
|
3f6dfa3dec | ||
|
|
f9ef297777 | ||
|
|
801b8998db | ||
|
|
92b7ad7554 | ||
|
|
18bb847488 | ||
|
|
47133604c3 | ||
|
|
80b93e412a | ||
|
|
e839f84537 | ||
|
|
a548e47f90 | ||
|
|
89e8658f49 | ||
|
|
6d255f24ab | ||
|
|
e8f0ba6ec7 | ||
|
|
60798f9346 | ||
|
|
c83f5d88cb | ||
|
|
2f2134412e | ||
|
|
1e6b6bb24f | ||
|
|
16de29dabd | ||
|
|
691809cd85 | ||
|
|
ce1df8d794 | ||
|
|
74be36d8a3 | ||
|
|
2bb7eb2f91 | ||
|
|
c4592aa65f | ||
|
|
9bac35b3f1 | ||
|
|
2a0f866f26 | ||
|
|
371238a882 | ||
|
|
67e7d1074e | ||
|
|
25c34d8bca | ||
|
|
75f3a618f0 | ||
|
|
9947f3973e | ||
|
|
a685517118 | ||
|
|
14482162fd | ||
|
|
0f757655b8 | ||
|
|
39fb266221 | ||
|
|
9b91b1b260 | ||
|
|
894e90f485 | ||
|
|
97bb52bbdd | ||
|
|
f5772334e1 | ||
|
|
bbcdd67b95 | ||
|
|
cfc1dc2379 | ||
|
|
770704f3a7 | ||
|
|
9980633ac3 | ||
|
|
746d3d54c2 |
9
lib/msdeploy/createlogin.sql
Normal file
9
lib/msdeploy/createlogin.sql
Normal file
@@ -0,0 +1,9 @@
|
||||
/**********************************************************************/
|
||||
/* Install.SQL */
|
||||
/* Creates a login and makes the user a member of db roles */
|
||||
/* */
|
||||
/* Modifications for SQL AZURE - ON MASTER */
|
||||
/**********************************************************************/
|
||||
|
||||
|
||||
CREATE LOGIN PlaceHolderForUser WITH PASSWORD = 'PlaceHolderForPassword'
|
||||
15
lib/msdeploy/createuser.sql
Normal file
15
lib/msdeploy/createuser.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
/**********************************************************************/
|
||||
/* CreateUser.SQL */
|
||||
/* Creates a user and makes the user a member of db roles */
|
||||
/* This script runs against the User database and requires connection string */
|
||||
/* Supports SQL Server and SQL AZURE */
|
||||
/**********************************************************************/
|
||||
|
||||
-- Create database user and map to login
|
||||
-- and add user to the datareader, datawriter, ddladmin and securityadmin roles
|
||||
--
|
||||
|
||||
CREATE USER PlaceHolderForUser FOR LOGIN PlaceHolderForUser;
|
||||
GO
|
||||
EXEC sp_addrolemember 'db_owner', PlaceHolderForUser;
|
||||
GO
|
||||
@@ -1,45 +0,0 @@
|
||||
/**********************************************************************/
|
||||
/* Install.SQL */
|
||||
/* Creates a login and makes the user a member of db roles */
|
||||
/* */
|
||||
/**********************************************************************/
|
||||
|
||||
-- Declare variables for database name, username and password
|
||||
DECLARE @dbName sysname,
|
||||
@dbUser sysname,
|
||||
@dbPwd nvarchar(max);
|
||||
|
||||
-- Set variables for database name, username and password
|
||||
SET @dbName = 'PlaceHolderForDb';
|
||||
SET @dbUser = 'PlaceHolderForUser';
|
||||
SET @dbPwd = 'PlaceHolderForPassword';
|
||||
|
||||
DECLARE @cmd nvarchar(max)
|
||||
|
||||
-- Create login
|
||||
IF( SUSER_SID(@dbUser) is null )
|
||||
BEGIN
|
||||
print '-- Creating login '
|
||||
SET @cmd = N'CREATE LOGIN ' + quotename(@dbUser) + N' WITH PASSWORD ='''+ replace(@dbPwd, '''', '''''') + N''''
|
||||
EXEC(@cmd)
|
||||
END
|
||||
|
||||
-- Create database user and map to login
|
||||
-- and add user to the datareader, datawriter, ddladmin and securityadmin roles
|
||||
--
|
||||
SET @cmd = N'USE ' + quotename(@DBName) + N';
|
||||
IF( NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = ''' + replace(@dbUser, '''', '''''') + N'''))
|
||||
BEGIN
|
||||
print ''-- Creating user'';
|
||||
CREATE USER ' + quotename(@dbUser) + N' FOR LOGIN ' + quotename(@dbUser) + N';
|
||||
print ''-- Adding user'';
|
||||
EXEC sp_addrolemember ''db_ddladmin'', ''' + replace(@dbUser, '''', '''''') + N''';
|
||||
print ''-- Adding user'';
|
||||
EXEC sp_addrolemember ''db_securityadmin'', ''' + replace(@dbUser, '''', '''''') + N''';
|
||||
print ''-- Adding user'';
|
||||
EXEC sp_addrolemember ''db_datareader'', ''' + replace(@dbUser, '''', '''''') + N''';
|
||||
print ''-- Adding user'';
|
||||
EXEC sp_addrolemember ''db_datawriter'', ''' + replace(@dbUser, '''', '''''') + N''';
|
||||
END'
|
||||
EXEC(@cmd)
|
||||
GO
|
||||
@@ -1,7 +1,13 @@
|
||||
<MSDeploy.iisApp>
|
||||
<iisapp path="Orchard" managedRuntimeVersion="v4.0" />
|
||||
<iisapp path="Orchard" managedRuntimeVersion="v4.0" />
|
||||
<setAcl path="Orchard/App_Data" setAclAccess="Modify" />
|
||||
<setAcl path="Orchard/Media" setAclAccess="Modify" />
|
||||
<setAcl path="Orchard/bin/HostRestart" setAclAccess="Modify" />
|
||||
<dbFullSql path="install.sql" />
|
||||
</MSDeploy.iisApp>
|
||||
|
||||
<!-- Runs SQL script to create login and assign permissions, requires transacted="false"
|
||||
This script runs as the database administrator provided in parameters.xml
|
||||
-->
|
||||
<dbfullsql path="createlogin.sql" transacted="false" />
|
||||
<dbfullsql path="createuser.sql" transacted="false" />
|
||||
|
||||
</MSDeploy.iisApp>
|
||||
@@ -47,19 +47,17 @@
|
||||
<!-- Prompts for the admin password and uses it for the administrator connection string.
|
||||
This is use to create a login and assign permissions. The SQL tag indicates it is a parameter required for SQL.
|
||||
The DbAdminPassword tag indicates it should be used when the user is creating a new database. If they're not, it can be filled in with the DbUserPassword value. -->
|
||||
<parameter name="Database Administrator Password" description="Password for the database administrator account." tags="New, Password, SQL, dbAdminPassword">
|
||||
<parameter name="Database Administrator Password" description="Password for the database administrator account." tags="Password, SQL, dbAdminPassword">
|
||||
</parameter>
|
||||
|
||||
<parameter name="Admin Connection String SqlServer"
|
||||
tags="SQLConnectionString, AdminConnectionString, Hidden, Validate" description="Automatically sets the connection string for the connection request."
|
||||
defaultValue="Data Source={Database Server};Initial Catalog={Database Name};User Id={Database Administrator};Password={Database Administrator Password}">
|
||||
<parameterEntry type="ProviderPath" scope="dbfullsql" match="install.sql" />
|
||||
<parameter name="Admin Connection String SqlServer1" tags="SQLConnectionString, sql, Hidden" description="Automatically sets the connection string for the connection request." defaultValue="Data Source={Database Server};Initial Catalog=MASTER;User Id={Database Administrator};Password={Database Administrator Password}">
|
||||
<parameterEntry type="ProviderPath" scope="dbfullsql" match="createlogin.sql" />
|
||||
</parameter>
|
||||
|
||||
<parameter name="Non-Admin Connection String SqlServer"
|
||||
tags="SQLConnectionString, UserConnectionString, Hidden" description="Automatically sets the connection string for the connection request."
|
||||
defaultValue="Data Source={Database Server};Initial Catalog={Database Name};User Id={Database Username};Password={Database Password}">
|
||||
<parameter name="Admin Connection String SqlServer2" tags="SQLConnectionString, SQL, Hidden" description="Automatically sets the connection string for the connection request." defaultValue="Data Source={Database Server};Initial Catalog={Database Name};User Id={Database Administrator};Password={Database Administrator Password}">
|
||||
<parameterEntry type="ProviderPath" scope="dbfullsql" match="createuser.sql" />
|
||||
</parameter>
|
||||
|
||||
|
||||
<parameter name="Orchard Connection String" friendlyName="Orchard Connection String" description="Orchard SQL Data Connection String Setting" defaultValue="" tags="Sql, SqlCE, SingleLineConnectionString, Hidden">
|
||||
<parameterEntry kind="TextFile" scope="\\Settings\.txt$" match="(?<=\s*DataConnectionString:\s+)[^\s].*[^\r\n]" />
|
||||
|
||||
@@ -13,7 +13,8 @@ var glob = require("glob"),
|
||||
uglify = require("gulp-uglify"),
|
||||
rename = require("gulp-rename"),
|
||||
concat = require("gulp-concat"),
|
||||
header = require("gulp-header");
|
||||
header = require("gulp-header"),
|
||||
fs = require("fs");
|
||||
|
||||
/*
|
||||
** GULP TASKS
|
||||
@@ -37,32 +38,53 @@ gulp.task("rebuild", function () {
|
||||
return merge(assetGroupTasks);
|
||||
});
|
||||
|
||||
// Continuous watch (each asset group is built whenever one of its inputs changes).
|
||||
|
||||
// Set "Watchers" as sub-processes in order to restart the task when Assets.json changes.
|
||||
gulp.task("watch", function () {
|
||||
var pathWin32 = require("path");
|
||||
getAssetGroups().forEach(function (assetGroup) {
|
||||
var watchPaths = assetGroup.inputPaths.concat(assetGroup.watchPaths);
|
||||
gulp.watch(watchPaths, function (event) {
|
||||
var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@";
|
||||
if (isConcat)
|
||||
console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'.");
|
||||
else
|
||||
console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group.");
|
||||
var doRebuild = true;
|
||||
var task = createAssetGroupTask(assetGroup, doRebuild);
|
||||
var watchers;
|
||||
function restart() {
|
||||
if (watchers) {
|
||||
watchers.forEach(function (w) {
|
||||
w.remove();
|
||||
w.end();
|
||||
});
|
||||
}
|
||||
watchers = [];
|
||||
// Continuous watch (each asset group is built whenever one of its inputs changes).
|
||||
getAssetGroups().forEach(function (assetGroup) {
|
||||
var watchPaths = assetGroup.inputPaths.concat(assetGroup.watchPaths);
|
||||
var watcher = gulp.watch(watchPaths, function (event) {
|
||||
var isConcat = path.basename(assetGroup.outputFileName, path.extname(assetGroup.outputFileName)) !== "@";
|
||||
if (isConcat)
|
||||
console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group with output '" + assetGroup.outputPath + "'.");
|
||||
else
|
||||
console.log("Asset file '" + event.path + "' was " + event.type + ", rebuilding asset group.");
|
||||
var doRebuild = true;
|
||||
var task = createAssetGroupTask(assetGroup, doRebuild);
|
||||
});
|
||||
watchers.push(watcher);
|
||||
});
|
||||
}
|
||||
var p;
|
||||
if (p) { p.exit(); }
|
||||
p = gulp.watch("Orchard.Web/{Core,Modules,Themes}/*/Assets.json", function (event) {
|
||||
console.log("Asset file '" + event.path + "' was " + event.type + ", resetting asset watchers.");
|
||||
restart();
|
||||
});
|
||||
restart();
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
** ASSET GROUPS
|
||||
*/
|
||||
|
||||
function getAssetGroups() {
|
||||
var assetManifestPaths = glob.sync("Orchard.Web/{Core,Modules,Themes}/*/Assets.json");
|
||||
var assetManifestPaths = glob.sync("Orchard.Web/{Core,Modules,Themes}/*/Assets.json", {});
|
||||
var assetGroups = [];
|
||||
assetManifestPaths.forEach(function (assetManifestPath) {
|
||||
var assetManifest = require("./" + assetManifestPath);
|
||||
var file = './' + assetManifestPath;
|
||||
var json = fs.readFileSync(file, 'utf8');
|
||||
assetManifest = eval(json);
|
||||
assetManifest.forEach(function (assetGroup) {
|
||||
resolveAssetGroupPaths(assetGroup, assetManifestPath);
|
||||
assetGroups.push(assetGroup);
|
||||
|
||||
@@ -264,9 +264,6 @@ namespace Orchard.Tests.Modules.DesignerTools.Services
|
||||
new JProperty("name", "TestingPart"),
|
||||
new JProperty("value", "ContentPart"),
|
||||
new JProperty("children", new JArray(
|
||||
new JObject(
|
||||
new JProperty("name", "Zones"),
|
||||
new JProperty("value", "ZoneCollection")),
|
||||
new JObject(
|
||||
new JProperty("name", "Id"),
|
||||
new JProperty("value", "0")),
|
||||
@@ -327,9 +324,6 @@ namespace Orchard.Tests.Modules.DesignerTools.Services
|
||||
new JProperty("name", "TestingPart"),
|
||||
new JProperty("value", "ContentPart"),
|
||||
new JProperty("children", new JArray(
|
||||
new JObject(
|
||||
new JProperty("name", "Zones"),
|
||||
new JProperty("value", "ZoneCollection")),
|
||||
new JObject(
|
||||
new JProperty("name", "Id"),
|
||||
new JProperty("value", "0")),
|
||||
|
||||
@@ -98,23 +98,23 @@ namespace Orchard.Tests.Modules.Recipes.Services {
|
||||
|
||||
[Test]
|
||||
public void HarvestRecipesFailsToFindRecipesWhenCalledWithNotExistingExtension() {
|
||||
var recipes = (List<Recipe>) _recipeHarvester.HarvestRecipes("cantfindme");
|
||||
var recipes = _recipeHarvester.HarvestRecipes("cantfindme");
|
||||
|
||||
Assert.That(recipes.Count, Is.EqualTo(0));
|
||||
Assert.That(recipes.Count(), Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void HarvestRecipesShouldHarvestRecipeXmlFiles() {
|
||||
var recipes = (List<Recipe>)_recipeHarvester.HarvestRecipes("Sample1");
|
||||
Assert.That(recipes.Count, Is.EqualTo(1));
|
||||
var recipes = _recipeHarvester.HarvestRecipes("Sample1");
|
||||
Assert.That(recipes.Count(), Is.EqualTo(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ParseRecipeLoadsRecipeMetaDataIntoModel() {
|
||||
var recipes = (List<Recipe>) _recipeHarvester.HarvestRecipes("Sample1");
|
||||
Assert.That(recipes.Count, Is.EqualTo(1));
|
||||
var recipes = _recipeHarvester.HarvestRecipes("Sample1");
|
||||
Assert.That(recipes.Count(), Is.EqualTo(1));
|
||||
|
||||
var sampleRecipe = recipes[0];
|
||||
var sampleRecipe = recipes.First();
|
||||
Assert.That(sampleRecipe.Name, Is.EqualTo("cms"));
|
||||
Assert.That(sampleRecipe.Description, Is.EqualTo("a sample Orchard recipe describing a cms"));
|
||||
Assert.That(sampleRecipe.Author, Is.EqualTo("orchard"));
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Autofac;
|
||||
using NUnit.Framework;
|
||||
using Orchard.Caching;
|
||||
@@ -78,6 +80,42 @@ namespace Orchard.Tests.Caching {
|
||||
Is.Not.SameAs(c2.CacheManager.GetCache<string, string>()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CacheManagerIsNotBlocking() {
|
||||
var hits = 0;
|
||||
string result = "";
|
||||
|
||||
Enumerable.Range(0, 5).AsParallel().ForAll(x =>
|
||||
result = _cacheManager.Get("testItem", ctx => {
|
||||
// by waiting for 100ms we expect all the calls to Get
|
||||
// to enter this lambda
|
||||
Thread.Sleep(100);
|
||||
hits++;
|
||||
return "testResult";
|
||||
})
|
||||
);
|
||||
|
||||
Assert.That(result, Is.EqualTo("testResult"));
|
||||
Assert.That(hits, Is.GreaterThan(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CacheManagerIsBlocking() {
|
||||
var hits = 0;
|
||||
string result = "";
|
||||
|
||||
Enumerable.Range(0, 5).AsParallel().ForAll(x =>
|
||||
result = _cacheManager.Get("testItem", true, ctx => {
|
||||
Thread.Sleep(100);
|
||||
hits++;
|
||||
return "testResult";
|
||||
})
|
||||
);
|
||||
|
||||
Assert.That(result, Is.EqualTo("testResult"));
|
||||
Assert.That(hits, Is.EqualTo(1));
|
||||
}
|
||||
|
||||
class ComponentOne {
|
||||
public ICacheManager CacheManager { get; set; }
|
||||
|
||||
|
||||
@@ -512,7 +512,7 @@ Features:
|
||||
Dependencies: Beta
|
||||
");
|
||||
|
||||
moduleExtensionFolder.Manifests.Add("Classic", @"
|
||||
themeExtensionFolder.Manifests.Add("Classic", @"
|
||||
Name: Classic
|
||||
Version: 1.0.3
|
||||
OrchardVersion: 1
|
||||
|
||||
@@ -4,7 +4,7 @@ using Orchard.Localization.Models;
|
||||
|
||||
namespace Orchard.Tests.Localization {
|
||||
|
||||
[TestFixture]
|
||||
[TestFixture()]
|
||||
public class DateTimePartsTests {
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -13,7 +12,8 @@ using Orchard.Localization.Services;
|
||||
|
||||
namespace Orchard.Tests.Localization {
|
||||
|
||||
[TestFixture]
|
||||
[TestFixture()]
|
||||
[Category("longrunning")]
|
||||
public class DefaultDateFormatterTests {
|
||||
|
||||
[SetUp]
|
||||
|
||||
@@ -89,9 +89,9 @@ namespace Orchard.WarmupStarter {
|
||||
var result = _initialization(application);
|
||||
_initializationResult = result;
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (Exception ex) {
|
||||
lock (_synLock) {
|
||||
_error = e;
|
||||
_error = ex;
|
||||
_previousError = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<autofac defaultAssembly="Orchard.Framework">
|
||||
|
||||
<!--
|
||||
To create tenant specific configurations, copy this file to ~/Congig/Sites.{tenant}.config
|
||||
To create tenant specific configurations, copy this file to ~/Config/Sites.{tenant}.config
|
||||
where {tenant} is the technical name of the targetted tenant
|
||||
|
||||
Allowed scopes: per-dependency, single-instance or per-lifetime-scope
|
||||
@@ -47,4 +47,4 @@
|
||||
</components>
|
||||
</autofac>
|
||||
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Orchard.Core.Containers.Drivers {
|
||||
if (updater != null) {
|
||||
var oldContainerId = model.ContainerId;
|
||||
updater.TryUpdateModel(model, "Containable", null, new[] { "ShowContainerPicker", "ShowPositionEditor" });
|
||||
if (oldContainerId != model.ContainerId) {
|
||||
if (oldContainerId != model.ContainerId && settings.ShowContainerPicker) {
|
||||
if (commonPart != null) {
|
||||
var containerItem = _contentManager.Get(model.ContainerId, VersionOptions.Latest);
|
||||
commonPart.Container = containerItem;
|
||||
@@ -61,20 +61,23 @@ namespace Orchard.Core.Containers.Drivers {
|
||||
part.Position = model.Position;
|
||||
}
|
||||
|
||||
var containers = _contentManager
|
||||
.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest)
|
||||
.List()
|
||||
.Where(container => container.ItemContentTypes.Any(type => type.Name == part.TypeDefinition.Name));
|
||||
if (settings.ShowContainerPicker) {
|
||||
var containers = _contentManager
|
||||
.Query<ContainerPart, ContainerPartRecord>(VersionOptions.Latest)
|
||||
.List()
|
||||
.Where(container => container.ItemContentTypes.Any(type => type.Name == part.TypeDefinition.Name));
|
||||
|
||||
var listItems = new[] { new SelectListItem { Text = T("(None)").Text, Value = "0" } }
|
||||
.Concat(containers.Select(x => new SelectListItem {
|
||||
Value = Convert.ToString(x.Id),
|
||||
Text = x.ContentItem.TypeDefinition.DisplayName + ": " + _contentManager.GetItemMetadata(x.ContentItem).DisplayText,
|
||||
Selected = x.Id == model.ContainerId,
|
||||
}))
|
||||
.ToList();
|
||||
var listItems = new[] { new SelectListItem { Text = T("(None)").Text, Value = "0" } }
|
||||
.Concat(containers.Select(x => new SelectListItem {
|
||||
Value = Convert.ToString(x.Id),
|
||||
Text = x.ContentItem.TypeDefinition.DisplayName + ": " + _contentManager.GetItemMetadata(x.ContentItem).DisplayText,
|
||||
Selected = x.Id == model.ContainerId,
|
||||
}))
|
||||
.ToList();
|
||||
|
||||
model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.ContainerId);
|
||||
}
|
||||
|
||||
model.AvailableContainers = new SelectList(listItems, "Value", "Text", model.ContainerId);
|
||||
model.Position = part.Position;
|
||||
|
||||
return shapeHelper.EditorTemplate(TemplateName: "Containable", Model: model, Prefix: "Containable");
|
||||
|
||||
@@ -88,6 +88,10 @@ namespace Orchard.Core.Containers.Drivers {
|
||||
|
||||
protected override DriverResult Editor(ContainerPart part, IUpdateModel updater, dynamic shapeHelper) {
|
||||
return ContentShape("Parts_Container_Edit", () => {
|
||||
if(!part.ContainerSettings.DisplayContainerEditor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var containables = !part.ContainerSettings.RestrictItemContentTypes ? _containerService.GetContainableTypes().ToList() : new List<ContentTypeDefinition>(0);
|
||||
var model = new ContainerViewModel {
|
||||
AdminMenuPosition = part.AdminMenuPosition,
|
||||
|
||||
@@ -48,6 +48,10 @@ namespace Orchard.Core.Containers.Settings {
|
||||
}
|
||||
|
||||
public class ContainerTypePartSettings {
|
||||
public ContainerTypePartSettings() {
|
||||
DisplayContainerEditor = true;
|
||||
}
|
||||
|
||||
public bool? ItemsShownDefault { get; set; }
|
||||
public int? PageSizeDefault { get; set; }
|
||||
public bool? PaginatedDefault { get; set; }
|
||||
@@ -55,6 +59,7 @@ namespace Orchard.Core.Containers.Settings {
|
||||
public bool RestrictItemContentTypes { get; set; }
|
||||
public bool? EnablePositioning { get; set; }
|
||||
public string AdminListViewName { get; set; }
|
||||
public bool DisplayContainerEditor { get; set; }
|
||||
}
|
||||
|
||||
public class ContainerSettingsHooks : ContentDefinitionEditorEventsBase {
|
||||
@@ -93,7 +98,8 @@ namespace Orchard.Core.Containers.Settings {
|
||||
EnablePositioning = model.EnablePositioning,
|
||||
AdminListViewName = model.AdminListViewName,
|
||||
AvailableItemContentTypes = _containerService.GetContainableTypes().ToList(),
|
||||
ListViewProviders = _listViewService.Providers.ToList()
|
||||
ListViewProviders = _listViewService.Providers.ToList(),
|
||||
DisplayContainerEditor = model.DisplayContainerEditor
|
||||
};
|
||||
|
||||
yield return DefinitionTemplate(viewModel);
|
||||
@@ -122,6 +128,7 @@ namespace Orchard.Core.Containers.Settings {
|
||||
builder.WithSetting("ContainerTypePartSettings.RestrictItemContentTypes", viewModel.RestrictItemContentTypes.ToString());
|
||||
builder.WithSetting("ContainerTypePartSettings.EnablePositioning", viewModel.EnablePositioning.ToString());
|
||||
builder.WithSetting("ContainerTypePartSettings.AdminListViewName", viewModel.AdminListViewName);
|
||||
builder.WithSetting("ContainerTypePartSettings.DisplayContainerEditor", viewModel.DisplayContainerEditor.ToString());
|
||||
yield return DefinitionTemplate(viewModel);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,5 +16,6 @@ namespace Orchard.Core.Containers.ViewModels {
|
||||
|
||||
[UIHint("ListViewPicker")]
|
||||
public string AdminListViewName { get; set; }
|
||||
public bool DisplayContainerEditor { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,11 @@
|
||||
@{
|
||||
Script.Require("ShapesBase");
|
||||
}
|
||||
<fieldset>
|
||||
@Html.CheckBoxFor(m => m.DisplayContainerEditor)
|
||||
@Html.LabelFor(m => m.DisplayContainerEditor, @T("Display settings editor").ToString(), new { @class = "forcheckbox" })
|
||||
<span class="hint">@T("When checked, users can change the settings for each content item.")</span>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<label for="@Html.FieldIdFor(m => m.ItemsShownDefault)">@T("Default Items Shown")</label>
|
||||
@Html.EditorFor(m => m.ItemsShownDefault)
|
||||
|
||||
@@ -65,8 +65,7 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
Pager pager = new Pager(_siteService.GetSiteSettings(), pagerParameters);
|
||||
|
||||
var versionOptions = VersionOptions.Latest;
|
||||
switch (model.Options.ContentsStatus)
|
||||
{
|
||||
switch (model.Options.ContentsStatus) {
|
||||
case ContentsStatus.Published:
|
||||
versionOptions = VersionOptions.Published;
|
||||
break;
|
||||
@@ -112,6 +111,10 @@ namespace Orchard.Core.Contents.Controllers {
|
||||
query = _cultureFilter.FilterCulture(query, model.Options.SelectedCulture);
|
||||
}
|
||||
|
||||
if(model.Options.ContentsStatus == ContentsStatus.Owner) {
|
||||
query = query.Where<CommonPartRecord>(cr => cr.OwnerId == Services.WorkContext.CurrentUser.Id);
|
||||
}
|
||||
|
||||
model.Options.SelectedFilter = model.TypeName;
|
||||
model.Options.FilterOptions = GetListableTypes(false)
|
||||
.Select(ctd => new KeyValuePair<string, string>(ctd.Name, ctd.DisplayName))
|
||||
|
||||
@@ -49,12 +49,12 @@ namespace Orchard.Core.Contents.ViewModels {
|
||||
Created
|
||||
}
|
||||
|
||||
public enum ContentsStatus
|
||||
{
|
||||
public enum ContentsStatus {
|
||||
Draft,
|
||||
Published,
|
||||
AllVersions,
|
||||
Latest
|
||||
Latest,
|
||||
Owner
|
||||
}
|
||||
|
||||
public enum ContentsBulkAction {
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
</select>
|
||||
<label for="contentResults" class="bulk-order">@T("Filter by")</label>
|
||||
<select id="contentResults" name="Options.ContentsStatus">
|
||||
@Html.SelectOption((ContentsStatus)Model.Options.ContentsStatus, ContentsStatus.Owner, T("owned by me").ToString())
|
||||
@Html.SelectOption((ContentsStatus)Model.Options.ContentsStatus, ContentsStatus.Latest, T("latest").ToString())
|
||||
@Html.SelectOption((ContentsStatus)Model.Options.ContentsStatus, ContentsStatus.Published, T("published").ToString())
|
||||
@Html.SelectOption((ContentsStatus)Model.Options.ContentsStatus, ContentsStatus.Draft, T("unpublished").ToString())
|
||||
|
||||
@@ -17,6 +17,7 @@ using Orchard.UI.Navigation;
|
||||
using Orchard.Utility;
|
||||
using System;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Exceptions;
|
||||
|
||||
namespace Orchard.Core.Navigation.Controllers {
|
||||
[ValidateInput(false)]
|
||||
@@ -179,6 +180,10 @@ namespace Orchard.Core.Navigation.Controllers {
|
||||
return View(model);
|
||||
}
|
||||
catch (Exception exception) {
|
||||
if (exception.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
|
||||
Logger.Error(T("Creating menu item failed: {0}", exception.Message).Text);
|
||||
Services.Notifier.Error(T("Creating menu item failed: {0}", exception.Message));
|
||||
return this.RedirectLocal(returnUrl, () => RedirectToAction("Index"));
|
||||
|
||||
@@ -11,6 +11,7 @@ using Orchard.Security.Permissions;
|
||||
using Orchard.UI;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.Utility;
|
||||
using Orchard.Exceptions;
|
||||
|
||||
namespace Orchard.Core.Navigation.Services {
|
||||
public class NavigationManager : INavigationManager {
|
||||
@@ -152,6 +153,9 @@ namespace Orchard.Core.Navigation.Services {
|
||||
items = builder.Build();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
Logger.Error(ex, "Unexpected error while querying a navigation provider. It was ignored. The menu provided by the provider may not be complete.");
|
||||
}
|
||||
if (items != null) {
|
||||
@@ -170,6 +174,9 @@ namespace Orchard.Core.Navigation.Services {
|
||||
items = builder.Build();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
Logger.Error(ex, "Unexpected error while querying a menu provider. It was ignored. The menu provided by the provider may not be complete.");
|
||||
}
|
||||
if (items != null) {
|
||||
@@ -188,6 +195,9 @@ namespace Orchard.Core.Navigation.Services {
|
||||
imageSets = builder.BuildImageSets();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
Logger.Error(ex, "Unexpected error while querying a navigation provider. It was ignored. The menu provided by the provider may not be complete.");
|
||||
}
|
||||
if (imageSets != null) {
|
||||
|
||||
@@ -9,6 +9,7 @@ using Orchard.Logging;
|
||||
using Orchard.Services;
|
||||
using Orchard.Tasks;
|
||||
using Orchard.Tasks.Scheduling;
|
||||
using Orchard.Exceptions;
|
||||
|
||||
namespace Orchard.Core.Scheduling.Services {
|
||||
[UsedImplicitly]
|
||||
@@ -65,6 +66,9 @@ namespace Orchard.Core.Scheduling.Services {
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
Logger.Warning(ex, "Unable to process scheduled task #{0} of type {1}", taskEntry.Id, taskEntry.Action);
|
||||
_transactionManager.Cancel();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using Orchard.Logging;
|
||||
using Orchard.Security;
|
||||
using Orchard.Settings;
|
||||
using Orchard.UI.Notify;
|
||||
using Orchard.Exceptions;
|
||||
|
||||
namespace Orchard.Core.Settings.Drivers {
|
||||
[UsedImplicitly]
|
||||
@@ -70,11 +71,12 @@ namespace Orchard.Core.Settings.Drivers {
|
||||
|
||||
var previousBaseUrl = model.Site.BaseUrl;
|
||||
|
||||
updater.TryUpdateModel(model, Prefix, null, new [] { "Site.SuperUser", "Site.MaxPageSize" });
|
||||
// Update all properties but not SuperUser, MaxPageSize and BaseUrl.
|
||||
updater.TryUpdateModel(model, Prefix, null, new [] { "Site.SuperUser", "Site.MaxPageSize", "Site.BaseUrl", "Site.MaxPagedCount" });
|
||||
|
||||
// only a user with SiteOwner permission can change the site owner
|
||||
if (_authorizer.Authorize(StandardPermissions.SiteOwner)) {
|
||||
updater.TryUpdateModel(model, Prefix, new[] { "Site.SuperUser", "Site.MaxPageSize" }, null);
|
||||
updater.TryUpdateModel(model, Prefix, new[] { "Site.SuperUser", "Site.MaxPageSize", "Site.BaseUrl", "Site.MaxPagedCount" }, null);
|
||||
|
||||
// ensures the super user is fully empty
|
||||
if (String.IsNullOrEmpty(model.SuperUser)) {
|
||||
@@ -87,27 +89,30 @@ namespace Orchard.Core.Settings.Drivers {
|
||||
updater.AddModelError("SuperUser", T("The user {0} was not found", model.SuperUser));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure the base url is absolute if provided
|
||||
if (!String.IsNullOrWhiteSpace(model.Site.BaseUrl)) {
|
||||
if (!Uri.IsWellFormedUriString(model.Site.BaseUrl, UriKind.Absolute)) {
|
||||
updater.AddModelError("BaseUrl", T("The base url must be absolute."));
|
||||
}
|
||||
// ensure the base url is absolute if provided
|
||||
if (!String.IsNullOrWhiteSpace(model.Site.BaseUrl)) {
|
||||
if (!Uri.IsWellFormedUriString(model.Site.BaseUrl, UriKind.Absolute)) {
|
||||
updater.AddModelError("BaseUrl", T("The base url must be absolute."));
|
||||
}
|
||||
// if the base url has been modified, try to ping it
|
||||
else if (!String.Equals(previousBaseUrl, model.Site.BaseUrl, StringComparison.OrdinalIgnoreCase)) {
|
||||
try {
|
||||
var request = WebRequest.Create(model.Site.BaseUrl) as HttpWebRequest;
|
||||
if (request != null) {
|
||||
using (request.GetResponse() as HttpWebResponse) {}
|
||||
else if (!String.Equals(previousBaseUrl, model.Site.BaseUrl, StringComparison.OrdinalIgnoreCase)) {
|
||||
try {
|
||||
var request = WebRequest.Create(model.Site.BaseUrl) as HttpWebRequest;
|
||||
if (request != null) {
|
||||
using (request.GetResponse() as HttpWebResponse) { }
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
_notifier.Warning(T("The base url you entered could not be requested from current location."));
|
||||
Logger.Warning(ex, "Could not query base url: {0}", model.Site.BaseUrl);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
_notifier.Warning(T("The base url you entered could not be requested from current location."));
|
||||
Logger.Warning(e, "Could not query base url: {0}", model.Site.BaseUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ContentShape("Parts_Settings_SiteSettingsPart",
|
||||
() => shapeHelper.EditorTemplate(TemplateName: "Parts.Settings.SiteSettingsPart", Model: model, Prefix: Prefix));
|
||||
|
||||
@@ -9,6 +9,7 @@ using Orchard.ContentManagement.MetaData.Services;
|
||||
using Orchard.Core.Settings.Metadata.Records;
|
||||
using Orchard.Data;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Exceptions;
|
||||
|
||||
namespace Orchard.Core.Settings.Metadata {
|
||||
public class ContentDefinitionManager : Component, IContentDefinitionManager {
|
||||
@@ -124,7 +125,7 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
}
|
||||
|
||||
private IDictionary<string, ContentTypeDefinition> AcquireContentTypeDefinitions() {
|
||||
return _cacheManager.Get("ContentTypeDefinitions", ctx => {
|
||||
return _cacheManager.Get("ContentTypeDefinitions", true, ctx => {
|
||||
MonitorContentDefinitionSignal(ctx);
|
||||
|
||||
AcquireContentPartDefinitions();
|
||||
@@ -139,7 +140,7 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
}
|
||||
|
||||
private IDictionary<string, ContentPartDefinition> AcquireContentPartDefinitions() {
|
||||
return _cacheManager.Get("ContentPartDefinitions", ctx => {
|
||||
return _cacheManager.Get("ContentPartDefinitions", true, ctx => {
|
||||
MonitorContentDefinitionSignal(ctx);
|
||||
|
||||
var contentPartDefinitionRecords = _partDefinitionRepository.Table
|
||||
@@ -152,7 +153,7 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
}
|
||||
|
||||
private IDictionary<string, ContentFieldDefinition> AcquireContentFieldDefinitions() {
|
||||
return _cacheManager.Get("ContentFieldDefinitions", ctx => {
|
||||
return _cacheManager.Get("ContentFieldDefinitions", true, ctx => {
|
||||
MonitorContentDefinitionSignal(ctx);
|
||||
|
||||
return _fieldDefinitionRepository.Table.Select(Build).ToDictionary(x => x.Name, y => y);
|
||||
@@ -282,6 +283,9 @@ namespace Orchard.Core.Settings.Metadata {
|
||||
return XElement.Parse(settings);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (ex.IsFatal()) {
|
||||
throw;
|
||||
}
|
||||
Logger.Error(ex, "Unable to parse settings xml");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Orchard.Core.Settings.Services {
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public ISite GetSiteSettings() {
|
||||
var siteId = _cacheManager.Get("SiteId", ctx => {
|
||||
var siteId = _cacheManager.Get("SiteId", true, ctx => {
|
||||
var site = _contentManager.Query("Site")
|
||||
.List()
|
||||
.FirstOrDefault();
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
</div>
|
||||
<div>
|
||||
<label for="@Html.FieldIdFor(m => m.BaseUrl)">@T("Base URL")</label>
|
||||
@Html.TextBoxFor(m => m.BaseUrl, new { @class = "text medium is-url" })
|
||||
@Html.TextBoxFor(m => m.BaseUrl,
|
||||
(object)(AuthorizedFor(Orchard.Security.StandardPermissions.SiteOwner)
|
||||
? (dynamic)new { @class = "text medium is-url" }
|
||||
: (dynamic)new { @class = "text medium is-url", @readonly = "readonly" }))
|
||||
<span class="hint">@T("Enter the fully qualified base URL of the web site.")</span>
|
||||
<span class="hint">@T("e.g., http://localhost:30320/orchardlocal, http://www.yourdomain.com")</span>
|
||||
</div>
|
||||
@@ -45,14 +48,15 @@
|
||||
@Html.EditorFor(x => x.PageTitleSeparator)
|
||||
@Html.ValidationMessage("PageTitleSeparator", "*")
|
||||
</div>
|
||||
@if (AuthorizedFor(Orchard.Security.StandardPermissions.SiteOwner)) {
|
||||
<div>
|
||||
<label for="SuperUser">@T("Super user")</label>
|
||||
@Html.EditorFor(x => x.SuperUser)
|
||||
@Html.TextBoxFor(x => x.SuperUser,
|
||||
(object)(AuthorizedFor(Orchard.Security.StandardPermissions.SiteOwner)
|
||||
? (dynamic)new { @class = "text single-line" }
|
||||
: (dynamic)new { @class = "text single-line", @readonly = "readonly" }))
|
||||
@Html.ValidationMessage("SuperUser", "*")
|
||||
<span class="hint">@T("Enter an existing account name, or nothing if you don't want a Super user account")</span>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<label for="SiteDebugMode">@T("Resource Debug Mode")</label>
|
||||
@Html.DropDownList("ResourceDebugMode", resourceDebugMode)
|
||||
|
||||
@@ -301,9 +301,12 @@ namespace Orchard.Core.Shapes {
|
||||
var progress = 1;
|
||||
var flatPositionComparer = new FlatPositionComparer();
|
||||
var ordering = unordered.Select(item => {
|
||||
var position = (item == null || item.GetType().GetProperty("Metadata") == null || item.Metadata.GetType().GetProperty("Position") == null)
|
||||
? null
|
||||
: item.Metadata.Position;
|
||||
string position = null;
|
||||
var itemPosition = item as IPositioned;
|
||||
if (itemPosition != null) {
|
||||
position = itemPosition.Position;
|
||||
}
|
||||
|
||||
return new { item, position };
|
||||
}).ToList();
|
||||
|
||||
|
||||
@@ -236,7 +236,13 @@
|
||||
}
|
||||
|
||||
if (_this.filter("[itemprop~='RemoveUrl']").length == 1) {
|
||||
if (!confirm(confirmRemoveMessage)) {
|
||||
// use a custom message if its set in data-message
|
||||
var dataMessage = _this.data('message');
|
||||
if (dataMessage === undefined) {
|
||||
dataMessage = confirmRemoveMessage;
|
||||
}
|
||||
|
||||
if (!confirm(dataMessage)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
<IISExpressAnonymousAuthentication />
|
||||
<IISExpressWindowsAuthentication />
|
||||
<IISExpressUseClassicPipelineMode />
|
||||
<UseGlobalApplicationHostFile />
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
@@ -71,6 +72,10 @@
|
||||
<Project>{9916839C-39FC-4CEB-A5AF-89CA7E87119F}</Project>
|
||||
<Name>Orchard.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Orchard.MediaLibrary\Orchard.MediaLibrary.csproj">
|
||||
<Project>{73a7688a-5bd3-4f7e-adfa-ce36c5a10e3b}</Project>
|
||||
<Name>Orchard.MediaLibrary</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Content\Admin\Images\grippie.png" />
|
||||
|
||||
@@ -5,70 +5,72 @@
|
||||
editors.each(function() {
|
||||
|
||||
var idPostfix = $(this).attr('id').substr('wmd-input'.length);
|
||||
|
||||
|
||||
var editor = new Markdown.Editor(converter, idPostfix, {
|
||||
handler: function() { window.open("http://daringfireball.net/projects/markdown/syntax"); }
|
||||
});
|
||||
|
||||
editor.hooks.set("insertImageDialog", function(callback) {
|
||||
// see if there's an image selected that they intend on editing
|
||||
var wmd = $('#wmd-input' + idPostfix);
|
||||
if (Boolean($(this).data("manage-media"))) {
|
||||
editor.hooks.set("insertImageDialog", function (callback) {
|
||||
// see if there's an image selected that they intend on editing
|
||||
var wmd = $('#wmd-input' + idPostfix);
|
||||
|
||||
var editImage, content = wmd.selection ? wmd.selection.createRange().text : null;
|
||||
var adminIndex = location.href.toLowerCase().indexOf("/admin/");
|
||||
if (adminIndex === -1) return;
|
||||
var url = location.href.substr(0, adminIndex) + "/Admin/Orchard.MediaLibrary?dialog=true";
|
||||
$.colorbox({
|
||||
href: url,
|
||||
iframe: true,
|
||||
reposition: true,
|
||||
width: "90%",
|
||||
height: "90%",
|
||||
onLoad: function () {
|
||||
// hide the scrollbars from the main window
|
||||
$('html, body').css('overflow', 'hidden');
|
||||
},
|
||||
onClosed: function () {
|
||||
$('html, body').css('overflow', '');
|
||||
var editImage, content = wmd.selection ? wmd.selection.createRange().text : null;
|
||||
var adminIndex = location.href.toLowerCase().indexOf("/admin/");
|
||||
if (adminIndex === -1) return;
|
||||
var url = location.href.substr(0, adminIndex) + "/Admin/Orchard.MediaLibrary?dialog=true";
|
||||
$.colorbox({
|
||||
href: url,
|
||||
iframe: true,
|
||||
reposition: true,
|
||||
width: "90%",
|
||||
height: "90%",
|
||||
onLoad: function () {
|
||||
// hide the scrollbars from the main window
|
||||
$('html, body').css('overflow', 'hidden');
|
||||
},
|
||||
onClosed: function () {
|
||||
$('html, body').css('overflow', '');
|
||||
|
||||
var selectedData = $.colorbox.selectedData;
|
||||
var selectedData = $.colorbox.selectedData;
|
||||
|
||||
if (selectedData == null) // Dialog cancelled, do nothing
|
||||
return;
|
||||
if (selectedData == null) // Dialog cancelled, do nothing
|
||||
return;
|
||||
|
||||
var newContent = '';
|
||||
for (var i = 0; i < selectedData.length; i++) {
|
||||
var renderMedia = location.href.substr(0, adminIndex) + "/Admin/Orchard.MediaLibrary/MediaItem/" + selectedData[i].id + "?displayType=Raw";
|
||||
$.ajax({
|
||||
async: false,
|
||||
type: 'GET',
|
||||
url: renderMedia,
|
||||
success: function (data) {
|
||||
newContent += data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var result = $.parseHTML(newContent);
|
||||
var img = $(result).filter('img');
|
||||
// if this is an image, use the callback which will format it in markdown
|
||||
if (img.length > 0 && img.attr('src')) {
|
||||
callback(img.attr('src'));
|
||||
}
|
||||
|
||||
// otherwise, insert the raw HTML
|
||||
else {
|
||||
if (wmd.selection) {
|
||||
wmd.selection.replace('.*', newContent);
|
||||
} else {
|
||||
wmd.text(newContent);
|
||||
var newContent = '';
|
||||
for (var i = 0; i < selectedData.length; i++) {
|
||||
var renderMedia = location.href.substr(0, adminIndex) + "/Admin/Orchard.MediaLibrary/MediaItem/" + selectedData[i].id + "?displayType=Raw";
|
||||
$.ajax({
|
||||
async: false,
|
||||
type: 'GET',
|
||||
url: renderMedia,
|
||||
success: function (data) {
|
||||
newContent += data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var result = $.parseHTML(newContent);
|
||||
var img = $(result).filter('img');
|
||||
// if this is an image, use the callback which will format it in markdown
|
||||
if (img.length > 0 && img.attr('src')) {
|
||||
callback(img.attr('src'));
|
||||
}
|
||||
|
||||
// otherwise, insert the raw HTML
|
||||
else {
|
||||
if (wmd.selection) {
|
||||
wmd.selection.replace('.*', newContent);
|
||||
} else {
|
||||
wmd.text(newContent);
|
||||
}
|
||||
callback();
|
||||
}
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
editor.run();
|
||||
});
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
{"id", "wmd-input" + "-" + idPostfix},
|
||||
{"class", "wmd-input"},
|
||||
{"data-mediapicker-uploadpath", Model.AddMediaPath},
|
||||
{"data-mediapicker-title", T("Insert/Update Media")}
|
||||
{"data-mediapicker-title", T("Insert/Update Media")},
|
||||
{"data-manage-media", AuthorizedFor(Orchard.MediaLibrary.Permissions.ManageMediaContent) ? "true" : "false" }
|
||||
};
|
||||
|
||||
// The markdown editor itself doesn't seem to (yet) support autofocus, but we'll set it on the textarea nonetheless.
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace Orchard.AntiSpam.Controllers {
|
||||
if (spam != null) {
|
||||
spam.As<SpamFilterPart>().Status = SpamStatus.Spam;
|
||||
_spamService.ReportSpam(spam.As<SpamFilterPart>());
|
||||
Services.ContentManager.Publish(spam);
|
||||
Services.ContentManager.Unpublish(spam);
|
||||
}
|
||||
|
||||
return this.RedirectLocal(returnUrl, "~/");
|
||||
@@ -158,7 +158,7 @@ namespace Orchard.AntiSpam.Controllers {
|
||||
var spam = Services.ContentManager.Get(id, VersionOptions.Latest);
|
||||
if (spam != null) {
|
||||
spam.As<SpamFilterPart>().Status = SpamStatus.Ham;
|
||||
_spamService.ReportSpam(spam.As<SpamFilterPart>());
|
||||
_spamService.ReportHam(spam.As<SpamFilterPart>());
|
||||
Services.ContentManager.Publish(spam);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using Orchard.AntiSpam.Models;
|
||||
using Orchard.AntiSpam.Services;
|
||||
using Orchard.AntiSpam.Settings;
|
||||
using Orchard.ContentManagement.Drivers;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
@@ -8,11 +7,9 @@ using Orchard.Localization;
|
||||
|
||||
namespace Orchard.AntiSpam.Drivers {
|
||||
public class SpamFilterPartDriver : ContentPartDriver<SpamFilterPart> {
|
||||
private readonly ISpamService _spamService;
|
||||
private const string TemplateName = "Parts/SpamFilter";
|
||||
|
||||
public SpamFilterPartDriver(IOrchardServices services, ISpamService spamService) {
|
||||
_spamService = spamService;
|
||||
public SpamFilterPartDriver(IOrchardServices services) {
|
||||
T = NullLocalizer.Instance;
|
||||
Services = services;
|
||||
}
|
||||
@@ -25,8 +22,6 @@ namespace Orchard.AntiSpam.Drivers {
|
||||
}
|
||||
|
||||
protected override DriverResult Editor(SpamFilterPart part, ContentManagement.IUpdateModel updater, dynamic shapeHelper) {
|
||||
part.Status = _spamService.CheckForSpam(part);
|
||||
|
||||
if (part.Settings.GetModel<SpamFilterPartSettings>().DeleteSpam) {
|
||||
updater.AddModelError("Spam", T("Spam detected."));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Orchard.AntiSpam.Models;
|
||||
|
||||
using Orchard.AntiSpam.Services;
|
||||
using Orchard.AntiSpam.Settings;
|
||||
using Orchard.ContentManagement.Handlers;
|
||||
using Orchard.Data;
|
||||
@@ -7,14 +7,22 @@ using Orchard.Data;
|
||||
namespace Orchard.AntiSpam.Handlers {
|
||||
public class SpamFilterPartHandler : ContentHandler {
|
||||
private readonly ITransactionManager _transactionManager;
|
||||
private readonly ISpamService _spamService;
|
||||
|
||||
public SpamFilterPartHandler(
|
||||
IRepository<SpamFilterPartRecord> repository,
|
||||
ITransactionManager transactionManager
|
||||
ITransactionManager transactionManager,
|
||||
ISpamService spamService
|
||||
) {
|
||||
_transactionManager = transactionManager;
|
||||
_spamService = spamService;
|
||||
|
||||
Filters.Add(StorageFilter.For(repository));
|
||||
|
||||
OnCreating<SpamFilterPart>((context, part) => {
|
||||
part.Status = _spamService.CheckForSpam(part);
|
||||
});
|
||||
|
||||
OnPublishing<SpamFilterPart>((context, part) => {
|
||||
if (part.Status == SpamStatus.Spam) {
|
||||
if (part.Settings.GetModel<SpamFilterPartSettings>().DeleteSpam) {
|
||||
|
||||
@@ -126,6 +126,7 @@ namespace Orchard.AntiSpam.Services {
|
||||
CommentAuthorEmail = _tokenizer.Replace(settings.CommentAuthorEmailPattern, data),
|
||||
CommentAuthorUrl = _tokenizer.Replace(settings.CommentAuthorUrlPattern, data),
|
||||
CommentContent = _tokenizer.Replace(settings.CommentContentPattern, data),
|
||||
CommentType = part.ContentItem.ContentType.ToLower()
|
||||
};
|
||||
|
||||
if(workContext.HttpContext != null) {
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace Orchard.Comments.Drivers {
|
||||
|
||||
// prevent users from commenting on a closed thread by hijacking the commentedOn property
|
||||
var commentsPart = commentedOn.As<CommentsPart>();
|
||||
if (!commentsPart.CommentsActive) {
|
||||
if (commentsPart == null || !commentsPart.CommentsActive) {
|
||||
_orchardServices.TransactionManager.Cancel();
|
||||
return Editor(part, shapeHelper);
|
||||
}
|
||||
|
||||
@@ -120,7 +120,8 @@ namespace Orchard.Comments.Services {
|
||||
}
|
||||
|
||||
public void DeleteComment(int commentId) {
|
||||
_orchardServices.ContentManager.Remove(_orchardServices.ContentManager.Get<CommentPart>(commentId).ContentItem);
|
||||
// Get latest because the comment may be unpublished if the anti-spam module has caught it
|
||||
_orchardServices.ContentManager.Remove(_orchardServices.ContentManager.Get<CommentPart>(commentId, VersionOptions.Latest).ContentItem);
|
||||
}
|
||||
|
||||
public bool CommentsDisabledForCommentedContent(int id) {
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Orchard.ContentPicker.Fields {
|
||||
|
||||
public IEnumerable<ContentItem> ContentItems {
|
||||
get {
|
||||
return _contentItems.Value;
|
||||
return _contentItems.Value ?? Enumerable.Empty<ContentItem>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Orchard.ContentTypes.Services {
|
||||
}
|
||||
|
||||
public IEnumerable<StereotypeDescription> GetStereotypes() {
|
||||
return _cacheManager.Get("ContentType.Stereotypes", context => {
|
||||
return _cacheManager.Get("ContentType.Stereotypes", true, context => {
|
||||
|
||||
// TODO: Implement a signal in ContentDefinitionManager that gets raised whenever a type definition is updated.
|
||||
// For now, we'll just cache the stereotypes for 1 minute.
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
<fieldset class="action">
|
||||
<button class="primaryAction" type="submit" name="submit.Save" value="Save">@T("Save")</button>
|
||||
<button class="primaryAction" type="submit" name="submit.Restore" value="Restore" itemprop="RemoveUrl">@T("Restore")</button>
|
||||
<button class="primaryAction" type="submit" name="submit.Restore" value="Restore" itemprop="RemoveUrl" data-message="@T("Are you sure you want to restore these placements?")">@T("Restore")</button>
|
||||
</fieldset>
|
||||
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ namespace Orchard.DynamicForms.Drivers {
|
||||
var runtimeValues = GetRuntimeValues(element);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(optionLabel)) {
|
||||
yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel };
|
||||
yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel, Value = string.Empty };
|
||||
}
|
||||
|
||||
if (queryId == null)
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace Orchard.DynamicForms.Drivers {
|
||||
var runtimeValues = GetRuntimeValues(element);
|
||||
|
||||
if (!String.IsNullOrWhiteSpace(optionLabel)) {
|
||||
yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel };
|
||||
yield return new SelectListItem { Text = displayType != "Design" ? _tokenizer.Replace(optionLabel, tokenData) : optionLabel, Value = string.Empty };
|
||||
}
|
||||
|
||||
if (taxonomyId == null)
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.Core.Contents.Extensions;
|
||||
using Orchard.Data;
|
||||
using Orchard.Data.Migration;
|
||||
|
||||
namespace Orchard.DynamicForms {
|
||||
public class Migrations : DataMigrationImpl {
|
||||
private readonly byte[] _oldLayoutHash = new byte[] { 0x91, 0x10, 0x3b, 0x97, 0xce, 0x1e, 0x1e, 0xc7, 0x7a, 0x41, 0xf7, 0x82, 0xe8, 0x58, 0x85, 0x91 };
|
||||
|
||||
private const string DefaultFormLayoutData =
|
||||
@"{
|
||||
""elements"": [
|
||||
@@ -59,7 +64,52 @@ namespace Orchard.DynamicForms {
|
||||
.WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData))
|
||||
.WithSetting("Stereotype", "Widget")
|
||||
.DisplayedAs("Form Widget"));
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
public int UpdateFrom1() {
|
||||
// if the default layout data was unchanged, fix it with the new default
|
||||
|
||||
var formLayoutPart = ContentDefinitionManager
|
||||
.GetTypeDefinition("Form")
|
||||
.Parts
|
||||
.FirstOrDefault(x => x.PartDefinition.Name == "LayoutPart");
|
||||
|
||||
if (formLayoutPart != null &&
|
||||
formLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"] != null) {
|
||||
var layout = formLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"];
|
||||
|
||||
if(GetMD5(layout) == _oldLayoutHash) {
|
||||
ContentDefinitionManager.AlterTypeDefinition("Form", type => type
|
||||
.WithPart("LayoutPart", p => p
|
||||
.WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
var formWidgetLayoutPart = ContentDefinitionManager
|
||||
.GetTypeDefinition("FormWidget")
|
||||
.Parts
|
||||
.FirstOrDefault(x => x.PartDefinition.Name == "LayoutPart");
|
||||
|
||||
if (formWidgetLayoutPart != null &&
|
||||
formWidgetLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"] != null) {
|
||||
var layout = formWidgetLayoutPart.Settings["LayoutTypePartSettings.DefaultLayoutData"];
|
||||
|
||||
if (GetMD5(layout) == _oldLayoutHash) {
|
||||
ContentDefinitionManager.AlterTypeDefinition("FormWidget", type => type
|
||||
.WithPart("LayoutPart", p => p
|
||||
.WithSetting("LayoutTypePartSettings.DefaultLayoutData", DefaultFormLayoutData))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
private byte[] GetMD5(string text) {
|
||||
byte[] encodedText = System.Text.Encoding.UTF8.GetBytes(text);
|
||||
return ((HashAlgorithm)CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
Name: Custom Forms
|
||||
Name: Dynamic Forms
|
||||
AntiForgery: enabled
|
||||
Author: The Orchard Team
|
||||
Website: http://orchardcustomforms.codeplex.com
|
||||
Website: http://www.orchardproject.net/
|
||||
Version: 1.9.1
|
||||
OrchardVersion: 1.9
|
||||
Description: Create custom forms like contact forms using layouts.
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Orchard.DynamicForms.Tokens {
|
||||
|
||||
public void Describe(DescribeContext context) {
|
||||
context.For("FormSubmission", T("Dynamic Form submission"), T("Dynamic Form Submission tokens for use in workflows handling the Dynamic Form Submitted event."))
|
||||
.Token("Field:*", T("Field:<field name>"), T("The posted field value to access."))
|
||||
.Token("Field:*", T("Field:<field name>"), T("The posted field value to access."), "Text")
|
||||
.Token("IsValid:*", T("IsValid:<field name>"), T("The posted field validation status."))
|
||||
;
|
||||
}
|
||||
@@ -15,10 +15,20 @@ namespace Orchard.DynamicForms.Tokens {
|
||||
public void Evaluate(EvaluateContext context) {
|
||||
context.For<FormSubmissionTokenContext>("FormSubmission")
|
||||
.Token(token => token.StartsWith("Field:", StringComparison.OrdinalIgnoreCase) ? token.Substring("Field:".Length) : null, GetFieldValue)
|
||||
.Chain(FilterChainParam, "Text", GetFieldValue)
|
||||
.Token(token => token.StartsWith("IsValid:", StringComparison.OrdinalIgnoreCase) ? token.Substring("IsValid:".Length) : null, GetFieldValidationStatus);
|
||||
}
|
||||
|
||||
private object GetFieldValue(string fieldName, FormSubmissionTokenContext context) {
|
||||
private static Tuple<string, string> FilterChainParam(string token) {
|
||||
int tokenLength = "Field:".Length;
|
||||
int chainIndex = token.IndexOf('.');
|
||||
if (token.StartsWith("Field:", StringComparison.OrdinalIgnoreCase) && chainIndex > tokenLength)
|
||||
return new Tuple<string, string>(token.Substring(tokenLength, chainIndex - tokenLength), token.Substring(chainIndex + 1));
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
private string GetFieldValue(string fieldName, FormSubmissionTokenContext context) {
|
||||
return context.PostedValues[fieldName];
|
||||
}
|
||||
|
||||
|
||||
@@ -8,34 +8,34 @@
|
||||
<label for="@Html.FieldIdFor(m => m.Value)" @if(settings.Required) { <text>class="required"</text> }>@Model.DisplayName</label>
|
||||
@switch (settings.ListMode) {
|
||||
case ListMode.Dropdown:
|
||||
@Html.DropDownListFor(m => m.Value, new SelectList(options, Model.Value))
|
||||
@Html.DropDownListFor(m => m.Value, new SelectList(options, Model.Value), settings.Required ? new {required = "required"} : null)
|
||||
break;
|
||||
|
||||
case ListMode.Radiobutton:
|
||||
foreach (var option in options) {
|
||||
if (string.IsNullOrWhiteSpace(option)) {
|
||||
<label>@Html.RadioButton("Value", "", string.IsNullOrWhiteSpace(Model.Value))<i>@T("unset")</i></label>
|
||||
}
|
||||
if (string.IsNullOrWhiteSpace(option)) {
|
||||
<label>@Html.RadioButton("Value", "", string.IsNullOrWhiteSpace(Model.Value), settings.Required ? new {required = "required"} : null)<i>@T("unset")</i></label>
|
||||
}
|
||||
else {
|
||||
<label>@Html.RadioButton("Value", option, (option == Model.Value))@option</label>
|
||||
}
|
||||
<label>@Html.RadioButton("Value", option, (option == Model.Value), settings.Required ? new {required = "required"} : null)@option</label>
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ListMode.Listbox:
|
||||
<input name="@Html.FieldNameFor(m => m.SelectedValues)" type="hidden" />
|
||||
@Html.ListBoxFor(m => m.SelectedValues, new MultiSelectList(options, Model.SelectedValues))
|
||||
break;
|
||||
@Html.ListBoxFor(m => m.SelectedValues, new MultiSelectList(options, Model.SelectedValues), settings.Required ? new {required = "required"} : null)
|
||||
break;
|
||||
|
||||
case ListMode.Checkbox:
|
||||
int index = 0;
|
||||
int index = 0;
|
||||
<input name="@Html.FieldNameFor(m => m.SelectedValues)" type="hidden" />
|
||||
foreach (var option in options) {
|
||||
index++;
|
||||
if (!string.IsNullOrWhiteSpace(option)) {
|
||||
<div>
|
||||
<input type="checkbox" name="@Html.FieldNameFor(m => m.SelectedValues)" value="@option" @((Model.SelectedValues != null && Model.SelectedValues.Contains(option)) ? "checked=\"checked\"" : "") class="check-box" id="@Html.FieldIdFor(m => m.SelectedValues)-@index" />
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.SelectedValues)-@index">@T(option)</label>
|
||||
<input type="checkbox" name="@Html.FieldNameFor(m => m.SelectedValues)" value="@option" @((Model.SelectedValues != null && Model.SelectedValues.Contains(option)) ? "checked=\"checked\"" : "") class="check-box" id="@Html.FieldIdFor(m => m.SelectedValues)-@index" @if(settings.Required) {<text> required="required"</text> } />
|
||||
<label class="forcheckbox" for="@Html.FieldIdFor(m => m.SelectedValues)-@index">@T(option)</label>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
|
||||
<fieldset>
|
||||
<label for="@Html.FieldIdFor(m => m.Value)" @if(Model.Settings.Required) { <text>class="required"</text> }>@Model.Field.DisplayName</label>
|
||||
@Html.TextBoxFor(m => m.Value, new { @class = "text small", type = "text", min = (Model.Settings.Minimum.HasValue) ? Model.Settings.Minimum.Value : 0, max = (Model.Settings.Maximum.HasValue) ? Model.Settings.Maximum.Value : 1000000, step = Math.Pow(10, 0 - Model.Settings.Scale).ToString(CultureInfo.InvariantCulture) })
|
||||
@(Model.Settings.Required
|
||||
? Html.TextBoxFor(m => m.Value, new {@class = "text-small", type = "text", min = (Model.Settings.Minimum.HasValue) ? Model.Settings.Minimum.Value : 0, max = (Model.Settings.Maximum.HasValue) ? Model.Settings.Maximum.Value : 1000000, step = Math.Pow(10, 0 - Model.Settings.Scale).ToString(CultureInfo.InvariantCulture), required = "required"})
|
||||
: Html.TextBoxFor(m => m.Value, new {@class = "text-small", type = "text", min = (Model.Settings.Minimum.HasValue) ? Model.Settings.Minimum.Value : 0, max = (Model.Settings.Maximum.HasValue) ? Model.Settings.Maximum.Value : 1000000, step = Math.Pow(10, 0 - Model.Settings.Scale).ToString(CultureInfo.InvariantCulture)}))
|
||||
@Html.ValidationMessageFor(m => m.Value)
|
||||
@if (HasText(Model.Settings.Hint)) {
|
||||
<span class="hint">@Model.Settings.Hint</span>
|
||||
|
||||
@@ -45,6 +45,15 @@ namespace Orchard.ImageEditor.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult Edit(string folderPath, string filename) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var media = Services.ContentManager.Query<MediaPart, MediaPartRecord>().Where(x => x.FolderPath == folderPath && x.FileName == filename).Slice(0, 1).FirstOrDefault();
|
||||
|
||||
if (media == null) {
|
||||
@@ -64,12 +73,21 @@ namespace Orchard.ImageEditor.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Upload(int id, string content, int width, int height) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var media = Services.ContentManager.Get(id).As<MediaPart>();
|
||||
|
||||
if (media == null) {
|
||||
return HttpNotFound();
|
||||
}
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(media.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
const string signature = "data:image/jpeg;base64,";
|
||||
|
||||
if (!content.StartsWith(signature, StringComparison.OrdinalIgnoreCase)) {
|
||||
@@ -96,7 +114,7 @@ namespace Orchard.ImageEditor.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Proxy(string url) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return HttpNotFound();
|
||||
|
||||
var sslFailureCallback = new RemoteCertificateValidationCallback((o, cert, chain, errors) => true);
|
||||
|
||||
@@ -11,9 +11,9 @@ namespace Orchard.Layouts {
|
||||
builder
|
||||
.AddImageSet("layouts")
|
||||
.Add(T("Layouts"), "8.5", layouts => layouts
|
||||
.Action("List", "Admin", new {id = "Layout", area = "Contents"})
|
||||
.Action("List", "Admin", new {id = "Layout", area = "Contents"}).Permission(Permissions.ManageLayouts)
|
||||
.LinkToFirstChild(false)
|
||||
.Add(T("Elements"), "1", elements => elements.Action("Index", "BlueprintAdmin", new {area = "Orchard.Layouts"})));
|
||||
.Add(T("Elements"), "1", elements => elements.Action("Index", "BlueprintAdmin", new {area = "Orchard.Layouts"}).Permission(Permissions.ManageLayouts)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,45 +74,6 @@
|
||||
return host.addElement(contentType);
|
||||
};
|
||||
|
||||
$scope.toggleInlineEditing = function () {
|
||||
if (!$scope.element.inlineEditingIsActive) {
|
||||
$scope.element.inlineEditingIsActive = true;
|
||||
$element.find(".layout-toolbar-container").show();
|
||||
var selector = "#layout-editor-" + $scope.$id + " .layout-html .layout-content-markup[data-templated=false]";
|
||||
var firstContentEditorId = $(selector).first().attr("id");
|
||||
tinymce.init({
|
||||
selector: selector,
|
||||
theme: "modern",
|
||||
schema: "html5",
|
||||
plugins: [
|
||||
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
|
||||
"searchreplace wordcount visualblocks visualchars code fullscreen",
|
||||
"insertdatetime media nonbreaking table contextmenu directionality",
|
||||
"emoticons template paste textcolor colorpicker textpattern",
|
||||
"fullscreen autoresize"
|
||||
],
|
||||
toolbar: "undo redo cut copy paste | bold italic | bullist numlist outdent indent formatselect | alignleft aligncenter alignright alignjustify ltr rtl | link unlink charmap | code fullscreen close",
|
||||
convert_urls: false,
|
||||
valid_elements: "*[*]",
|
||||
// Shouldn't be needed due to the valid_elements setting, but TinyMCE would strip script.src without it.
|
||||
extended_valid_elements: "script[type|defer|src|language]",
|
||||
statusbar: false,
|
||||
skin: "orchardlightgray",
|
||||
inline: true,
|
||||
fixed_toolbar_container: "#layout-editor-" + $scope.$id + " .layout-toolbar-container",
|
||||
init_instance_callback: function (editor) {
|
||||
if (editor.id == firstContentEditorId)
|
||||
tinymce.execCommand("mceFocus", false, editor.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
tinymce.remove("#layout-editor-" + $scope.$id + " .layout-content-markup");
|
||||
$element.find(".layout-toolbar-container").hide();
|
||||
$scope.element.inlineEditingIsActive = false;
|
||||
}
|
||||
};
|
||||
|
||||
$(document).on("cut copy paste", function (e) {
|
||||
// If the pseudo clipboard was already invoked (which happens on the first clipboard
|
||||
// operation after page load even if native clipboard support exists) then sit this
|
||||
@@ -164,23 +125,12 @@
|
||||
element.find(".layout-toolbar-container").click(function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
// Intercept mousedown on editor while in inline editing mode to
|
||||
// prevent current editor from losing focus.
|
||||
element.mousedown(function (e) {
|
||||
if (scope.element.inlineEditingIsActive) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
})
|
||||
// Unfocus and unselect everything on click outside of canvas.
|
||||
$(window).click(function (e) {
|
||||
// Except when in inline editing mode.
|
||||
if (!scope.element.inlineEditingIsActive) {
|
||||
scope.$apply(function () {
|
||||
scope.element.activeElement = null;
|
||||
scope.element.focusedElement = null;
|
||||
});
|
||||
}
|
||||
scope.$apply(function () {
|
||||
scope.element.activeElement = null;
|
||||
scope.element.focusedElement = null;
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,13 +35,6 @@
|
||||
templateUrl: environment.templateUrl("Html"),
|
||||
replace: true,
|
||||
link: function (scope, element) {
|
||||
// Mouse down events must not be intercepted by drag and drop while inline editing is active,
|
||||
// otherwise clicks in inline editors will have no effect.
|
||||
element.find(".layout-content-markup").mousedown(function (e) {
|
||||
if (scope.element.editor.inlineEditingIsActive) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
var resetFocus = false;
|
||||
var element = $scope.element;
|
||||
|
||||
if (element.editor.isDragging || element.editor.inlineEditingIsActive)
|
||||
if (element.editor.isDragging)
|
||||
return;
|
||||
|
||||
// If native clipboard support exists, the pseudo-clipboard will have been disabled.
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
this.focusedElement = null;
|
||||
this.dropTargetElement = null;
|
||||
this.isDragging = false;
|
||||
this.inlineEditingIsActive = false;
|
||||
this.isResizing = false;
|
||||
|
||||
this.resetToolboxElements = function () {
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
this.setIsActive = function (value) {
|
||||
if (!this.editor)
|
||||
return;
|
||||
if (this.editor.isDragging || this.editor.inlineEditingIsActive || this.editor.isResizing)
|
||||
if (this.editor.isDragging || this.editor.isResizing)
|
||||
return;
|
||||
|
||||
if (value)
|
||||
@@ -76,7 +76,7 @@
|
||||
return;
|
||||
if (this.isTemplated)
|
||||
return;
|
||||
if (this.editor.isDragging || this.editor.inlineEditingIsActive || this.editor.isResizing)
|
||||
if (this.editor.isDragging || this.editor.isResizing)
|
||||
return;
|
||||
|
||||
this.editor.focusedElement = this;
|
||||
|
||||
@@ -34,7 +34,8 @@ namespace Orchard.Layouts.Controllers {
|
||||
ICultureAccessor cultureAccessor,
|
||||
IShapeFactory shapeFactory,
|
||||
ITransactionManager transactionManager,
|
||||
ISignals signals) {
|
||||
ISignals signals,
|
||||
IOrchardServices orchardServices) {
|
||||
|
||||
_elementBlueprintService = elementBlueprintService;
|
||||
_notifier = notifier;
|
||||
@@ -43,12 +44,19 @@ namespace Orchard.Layouts.Controllers {
|
||||
_shapeFactory = shapeFactory;
|
||||
_transactionManager = transactionManager;
|
||||
_signals = signals;
|
||||
Services = orchardServices;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult Index() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprints = _elementBlueprintService.GetBlueprints().ToArray();
|
||||
var viewModel = new BlueprintsIndexViewModel {
|
||||
Blueprints = blueprints
|
||||
@@ -57,6 +65,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Browse() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var categories = RemoveBlueprints(_elementManager.GetCategories(DescribeElementsContext.Empty)).ToArray();
|
||||
var viewModel = new BrowseElementsViewModel {
|
||||
Categories = categories
|
||||
@@ -65,6 +77,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Create(string id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
if (String.IsNullOrWhiteSpace(id))
|
||||
return RedirectToAction("Browse");
|
||||
|
||||
@@ -80,6 +96,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Create(string id, CreateElementBlueprintViewModel model) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, id);
|
||||
var baseElement = _elementManager.ActivateElement(descriptor);
|
||||
@@ -100,7 +120,11 @@ namespace Orchard.Layouts.Controllers {
|
||||
return RedirectToAction("Edit", new { id = blueprint.Id });
|
||||
}
|
||||
|
||||
public ViewResult Edit(int id) {
|
||||
public ActionResult Edit(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
|
||||
@@ -125,6 +149,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
[HttpPost]
|
||||
[ValidateInput(false)]
|
||||
public ActionResult Edit(int id, ElementDataViewModel model) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
|
||||
@@ -154,6 +182,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Properties(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
|
||||
@@ -171,6 +203,10 @@ namespace Orchard.Layouts.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Properties(int id, ElementBlueprintPropertiesViewModel model) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
var describeContext = DescribeElementsContext.Empty;
|
||||
var descriptor = _elementManager.GetElementDescriptorByTypeName(describeContext, blueprint.BaseElementTypeName);
|
||||
@@ -191,7 +227,12 @@ namespace Orchard.Layouts.Controllers {
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Delete(int id) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var blueprint = _elementBlueprintService.GetBlueprint(id);
|
||||
|
||||
if (blueprint == null)
|
||||
@@ -204,7 +245,12 @@ namespace Orchard.Layouts.Controllers {
|
||||
|
||||
[FormValueRequired("submit.BulkEdit")]
|
||||
[ActionName("Index")]
|
||||
[HttpPost]
|
||||
public ActionResult BulkDelete(IEnumerable<int> blueprintIds) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageLayouts, T("Not authorized to manage layouts."))) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
if (blueprintIds == null || !blueprintIds.Any()) {
|
||||
_notifier.Error(T("Please select the blueprints to delete."));
|
||||
}
|
||||
|
||||
@@ -142,18 +142,7 @@ namespace Orchard.Layouts.Controllers {
|
||||
_objectStore.Set(session, state);
|
||||
return RedirectToAction("Edit", new {session = session});
|
||||
}
|
||||
|
||||
public RedirectToRouteResult Add(string session, string typeName, int? contentId = null, string contentType = null) {
|
||||
var state = new ElementSessionState {
|
||||
TypeName = typeName,
|
||||
ContentId = contentId,
|
||||
ContentType = contentType
|
||||
};
|
||||
|
||||
_objectStore.Set(session, state);
|
||||
return RedirectToAction("Edit", new { session = session });
|
||||
}
|
||||
|
||||
|
||||
public ViewResult Edit(string session) {
|
||||
var sessionState = _objectStore.Get<ElementSessionState>(session);
|
||||
var contentId = sessionState.ContentId;
|
||||
|
||||
@@ -6,6 +6,7 @@ using Orchard.ContentManagement;
|
||||
using Orchard.Layouts.Elements;
|
||||
using Orchard.Layouts.Framework.Elements;
|
||||
using Orchard.Layouts.Services;
|
||||
using Orchard.Localization;
|
||||
using Orchard.UI.Admin;
|
||||
|
||||
namespace Orchard.Layouts.Controllers {
|
||||
@@ -15,15 +16,25 @@ namespace Orchard.Layouts.Controllers {
|
||||
private readonly ILayoutManager _layoutManager;
|
||||
private readonly ILayoutModelMapper _mapper;
|
||||
|
||||
public LayoutController(IContentManager contentManager, ILayoutManager layoutManager, ILayoutModelMapper mapper) {
|
||||
public LayoutController(
|
||||
IContentManager contentManager,
|
||||
ILayoutManager layoutManager,
|
||||
ILayoutModelMapper mapper,
|
||||
IOrchardServices orchardServices) {
|
||||
|
||||
_contentManager = contentManager;
|
||||
_layoutManager = layoutManager;
|
||||
_mapper = mapper;
|
||||
Services = orchardServices;
|
||||
|
||||
T = NullLocalizer.Instance;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
public Localizer T { get; set; }
|
||||
|
||||
[HttpPost, ValidateInput(enableValidation: false)]
|
||||
public ContentResult ApplyTemplate(int? templateId = null, string layoutData = null, int? contentId = null, string contentType = null) {
|
||||
public ActionResult ApplyTemplate(int? templateId = null, string layoutData = null, int? contentId = null, string contentType = null) {
|
||||
var template = templateId != null ? _layoutManager.GetLayout(templateId.Value) : null;
|
||||
var templateElements = template != null ? _layoutManager.LoadElements(template).ToList() : default(IEnumerable<Element>);
|
||||
var describeContext = CreateDescribeElementsContext(contentId, contentType);
|
||||
|
||||
@@ -307,10 +307,9 @@ namespace Orchard.Layouts.Drivers {
|
||||
|
||||
var queryPart = query.As<QueryPart>();
|
||||
var layoutIndex = XmlHelper.Parse<int>(context.ExportableData.Get("LayoutIndex"));
|
||||
var layout = queryPart.Layouts[layoutIndex];
|
||||
|
||||
element.QueryId = queryPart.Id;
|
||||
element.LayoutId = layout.Id;
|
||||
element.LayoutId = layoutIndex != -1 ? queryPart.Layouts[layoutIndex].Id : -1;
|
||||
}
|
||||
|
||||
private static string GetLayoutDescription(IEnumerable<LayoutDescriptor> layouts, LayoutRecord l) {
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace Orchard.Layouts {
|
||||
.WithPart("LayoutPart", p => p
|
||||
.WithSetting("LayoutTypePartSettings.IsTemplate", "True"))
|
||||
.DisplayedAs("Layout")
|
||||
.Listable()
|
||||
.Draftable());
|
||||
|
||||
ContentDefinitionManager.AlterTypeDefinition("LayoutWidget", type => type
|
||||
|
||||
@@ -351,6 +351,7 @@
|
||||
<Compile Include="Helpers\PrefixHelper.cs" />
|
||||
<Compile Include="Helpers\JsonHelper.cs" />
|
||||
<Compile Include="Helpers\StringHelper.cs" />
|
||||
<Compile Include="Permissions.cs" />
|
||||
<Compile Include="Providers\BlueprintElementHarvester.cs" />
|
||||
<Compile Include="ResourceManifest.cs" />
|
||||
<Compile Include="Services\CurrentControllerAccessor.cs" />
|
||||
|
||||
40
src/Orchard.Web/Modules/Orchard.Layouts/Permissions.cs
Normal file
40
src/Orchard.Web/Modules/Orchard.Layouts/Permissions.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.Layouts {
|
||||
public class Permissions : IPermissionProvider {
|
||||
public static readonly Permission ManageLayouts = new Permission { Description = "Managing Layouts", Name = "ManageLayouts" };
|
||||
|
||||
public virtual Feature Feature { get; set; }
|
||||
|
||||
public IEnumerable<Permission> GetPermissions() {
|
||||
return new[] {
|
||||
ManageLayouts,
|
||||
};
|
||||
}
|
||||
|
||||
public IEnumerable<PermissionStereotype> GetDefaultStereotypes() {
|
||||
return new[] {
|
||||
new PermissionStereotype {
|
||||
Name = "Administrator",
|
||||
Permissions = new[] { ManageLayouts }
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Editor",
|
||||
Permissions = new[] { ManageLayouts }
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Moderator",
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Author"
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Contributor",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -38,7 +38,7 @@ namespace Orchard.Layouts.Services {
|
||||
public IEnumerable<ElementDescriptor> DescribeElements(DescribeElementsContext context) {
|
||||
var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string);
|
||||
var cacheKey = String.Format("LayoutElementTypes-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam);
|
||||
return _cacheManager.Get(cacheKey, acquireContext => {
|
||||
return _cacheManager.Get(cacheKey, true, acquireContext => {
|
||||
var harvesterContext = new HarvestElementsContext {
|
||||
Content = context.Content
|
||||
};
|
||||
@@ -55,7 +55,7 @@ namespace Orchard.Layouts.Services {
|
||||
|
||||
public IEnumerable<CategoryDescriptor> GetCategories(DescribeElementsContext context) {
|
||||
var contentType = context.Content != null ? context.Content.ContentItem.ContentType : default(string);
|
||||
return _cacheManager.Get(String.Format("ElementCategories-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam), acquireContext => {
|
||||
return _cacheManager.Get(String.Format("ElementCategories-{0}-{1}", contentType ?? "AnyType", context.CacheVaryParam), true, acquireContext => {
|
||||
var elements = DescribeElements(context);
|
||||
var categoryDictionary = GetCategories();
|
||||
var categoryDescriptorDictionary = new Dictionary<string, CategoryDescriptor>();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@foreach (var contentItemShape in Model.ContentItems) {
|
||||
var contentItem = (ContentItem)contentItemShape.ContentItem;
|
||||
var displayTextHtmlString = Html.ItemDisplayText(contentItem);
|
||||
var displayText = displayTextHtmlString != null ? displayTextHtmlString.ToString() : T("-").ToString();
|
||||
var displayText = displayTextHtmlString != null ? (IHtmlString)displayTextHtmlString : T("-");
|
||||
<div class="layout-snippet">
|
||||
@displayText
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
<div class="layout-toolbox-wrapper">
|
||||
<div class="layout-toolbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-checked="element.inlineEditingIsActive" ng-click="toggleInlineEditing()" />
|
||||
@T("Edit HTML content inline")
|
||||
</label>
|
||||
<ul class="layout-toolbox-groups" ng-hide="element.inlineEditingIsActive">
|
||||
<ul class="layout-toolbox-groups">
|
||||
<li class="layout-toolbox-group" ng-class="{collapsed: layoutIsCollapsed}">
|
||||
<a href="#" class="layout-toolbox-group-heading" ng-click="toggleLayoutIsCollapsed($event)">@T("Layout")</a>
|
||||
<ul class="layout-toolbox-items">
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
}
|
||||
<div class="item-properties actions">
|
||||
<p>
|
||||
@Html.ActionLink(T("{0} Properties", (string)Model.ContainerDisplayName).ToString(), "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl })
|
||||
@Html.ActionLink(T("{0} Properties", (string)Model.ContainerDisplayName), "Edit", new { Area = "Contents", Id = (int)Model.ContainerId, ReturnUrl = Html.ViewContext.HttpContext.Request.RawUrl })
|
||||
</p>
|
||||
</div>
|
||||
<div class="manage">
|
||||
@if (itemContentTypes.Any()) {
|
||||
foreach (var contentType in itemContentTypes) {
|
||||
@Html.ActionLink(T("New {0}", contentType.DisplayName).ToString(), "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" })
|
||||
@Html.ActionLink(T("New {0}", contentType.DisplayName), "Create", "Admin", new { area = "Contents", id = contentType.Name, containerId }, new { @class = "button primaryAction create-content" })
|
||||
}
|
||||
}
|
||||
else {
|
||||
@Html.ActionLink(T("New Content").ToString(), "Create", "Admin", new { area = "Contents", containerId }, new { @class = "button primaryAction create-content" })
|
||||
@Html.ActionLink(T("New Content"), "Create", "Admin", new { area = "Contents", containerId }, new { @class = "button primaryAction create-content" })
|
||||
}
|
||||
<a id="chooseItems" href="#" class="button primaryAction">@T("Choose Items")</a>
|
||||
</div>
|
||||
|
||||
@@ -53,10 +53,7 @@ namespace Orchard.Localization.Controllers {
|
||||
var contentItemTranslation = _contentManager.New<LocalizationPart>(masterContentItem.ContentType);
|
||||
contentItemTranslation.MasterContentItem = masterContentItem;
|
||||
|
||||
// build the editor using the master content item so that
|
||||
// the form is pre-populated with the original values
|
||||
|
||||
var content = _contentManager.BuildEditor(masterContentItem);
|
||||
var content = _contentManager.BuildEditor(contentItemTranslation);
|
||||
|
||||
return View(content);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary {
|
||||
builder.AddImageSet("media-library")
|
||||
.Add(T("Media"), "6",
|
||||
menu => menu.Add(T("Media"), "0", item => item.Action("Index", "Admin", new { area = "Orchard.MediaLibrary" })
|
||||
.Permission(Permissions.ManageMediaContent)));
|
||||
.Permission(Permissions.ManageOwnMedia)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ using Orchard.Themes;
|
||||
using Orchard.UI.Navigation;
|
||||
using Orchard.ContentManagement.MetaData;
|
||||
using Orchard.Validation;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Orchard.MediaLibrary.Controllers {
|
||||
[ValidateInput(false)]
|
||||
@@ -41,17 +42,21 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
public ILogger Logger { get; set; }
|
||||
|
||||
public ActionResult Index(string folderPath = "", bool dialog = false) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// If the user is trying to access a folder above his boundaries, redirect him to his home folder
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return RedirectToAction("Index", new { folderPath = rootMediaFolder.MediaPath, dialog });
|
||||
}
|
||||
|
||||
// let other modules enhance the ui by providing custom navigation and actions
|
||||
var explorer = Services.ContentManager.New("MediaLibraryExplorer");
|
||||
explorer.Weld(new MediaLibraryExplorerPart());
|
||||
|
||||
var explorerShape = Services.ContentManager.BuildDisplay(explorer);
|
||||
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
|
||||
var viewModel = new MediaManagerIndexViewModel {
|
||||
DialogMode = dialog,
|
||||
FolderPath = folderPath,
|
||||
@@ -73,7 +78,7 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Import(string folderPath) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot import media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot import media")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var mediaProviderMenu = _navigationManager.BuildMenu("mediaproviders");
|
||||
@@ -91,9 +96,20 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult MediaItems(string folderPath, int skip = 0, int count = 0, string order = "created", string mediaType = "") {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
var model = new MediaManagerMediaItemsViewModel {
|
||||
MediaItems = new List<MediaManagerMediaItemViewModel>(),
|
||||
MediaItemsCount = 0,
|
||||
FolderPath = folderPath
|
||||
};
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var mediaParts = _mediaLibraryService.GetMediaContentItems(folderPath, skip, count, order, mediaType, VersionOptions.Latest);
|
||||
var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(folderPath, mediaType, VersionOptions.Latest);
|
||||
|
||||
@@ -113,9 +129,19 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult ChildFolders(string folderPath = null) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot get child folder listing")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot get child folder listing")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
var model = new MediaManagerChildFoldersViewModel {
|
||||
Children = new IMediaFolder[0]
|
||||
};
|
||||
|
||||
return View(model);
|
||||
}
|
||||
|
||||
var viewModel = new MediaManagerChildFoldersViewModel {
|
||||
Children = _mediaLibraryService.GetMediaFolders(folderPath)
|
||||
};
|
||||
@@ -127,11 +153,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult RecentMediaItems(int skip = 0, int count = 0, string order = "created", string mediaType = "") {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Cannot view media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Cannot view media")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var mediaParts = _mediaLibraryService.GetMediaContentItems(skip, count, order, mediaType);
|
||||
var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(mediaType);
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder().MediaPath;
|
||||
|
||||
var mediaParts = _mediaLibraryService.GetMediaContentItems(rootMediaFolder, skip, count, order, mediaType);
|
||||
var mediaPartsCount = _mediaLibraryService.GetMediaContentItemsCount(rootMediaFolder, mediaType);
|
||||
|
||||
|
||||
var mediaItems = mediaParts.Select(x => new MediaManagerMediaItemViewModel {
|
||||
@@ -149,12 +177,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[Themed(false)]
|
||||
public ActionResult MediaItem(int id, string displayType = "SummaryAdmin") {
|
||||
var contentItem = Services.ContentManager.Get(id, VersionOptions.Latest);
|
||||
var contentItem = Services.ContentManager.Get<MediaPart>(id, VersionOptions.Latest);
|
||||
|
||||
if (contentItem == null)
|
||||
return HttpNotFound();
|
||||
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, contentItem, T("Cannot view media")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, contentItem, T("Cannot view media"))
|
||||
|| !_mediaLibraryService.CanManageMediaFolder(contentItem.FolderPath))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
dynamic model = Services.ContentManager.BuildDisplay(contentItem, displayType);
|
||||
@@ -164,13 +193,20 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Delete(int[] mediaItemIds) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't delete media items")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't delete media items")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var mediaItems = Services.ContentManager
|
||||
.Query(VersionOptions.Latest)
|
||||
.ForContentItems(mediaItemIds)
|
||||
.List()
|
||||
.Select(x => x.As<MediaPart>())
|
||||
.Where(x => x != null);
|
||||
|
||||
try {
|
||||
foreach (var media in Services.ContentManager.Query(VersionOptions.Latest).ForContentItems(mediaItemIds).List()) {
|
||||
if (media != null) {
|
||||
Services.ContentManager.Remove(media);
|
||||
foreach (var media in mediaItems) {
|
||||
if (_mediaLibraryService.CanManageMediaFolder(media.FolderPath)) {
|
||||
Services.ContentManager.Remove(media.ContentItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,12 +220,16 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Clone(int mediaItemId) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't clone media items")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't clone media items")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
try {
|
||||
var media = Services.ContentManager.Get(mediaItemId).As<MediaPart>();
|
||||
|
||||
if(!_mediaLibraryService.CanManageMediaFolder(media.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var newFileName = Path.GetFileNameWithoutExtension(media.FileName) + " Copy" + Path.GetExtension(media.FileName);
|
||||
|
||||
_mediaLibraryService.CopyFile(media.FolderPath, media.FileName, media.FolderPath, newFileName);
|
||||
|
||||
@@ -15,11 +15,17 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
private readonly IMediaLibraryService _mediaLibraryService;
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public ClientStorageController(IMediaLibraryService mediaManagerService, IContentManager contentManager) {
|
||||
public ClientStorageController(
|
||||
IMediaLibraryService mediaManagerService,
|
||||
IContentManager contentManager,
|
||||
IOrchardServices orchardServices) {
|
||||
_mediaLibraryService = mediaManagerService;
|
||||
_contentManager = contentManager;
|
||||
Services = orchardServices;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
public ActionResult Index(string folderPath, string type) {
|
||||
|
||||
var viewModel = new ImportMediaViewModel {
|
||||
@@ -32,6 +38,15 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Upload(string folderPath, string type) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var statuses = new List<object>();
|
||||
|
||||
// Loop through each file in the request
|
||||
|
||||
@@ -32,9 +32,15 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public ActionResult Create(string folderPath) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't create media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't create media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// If the user is trying to access a folder above his boundaries, redirect him to his home folder
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return RedirectToAction("Create", new { folderPath = rootMediaFolder.MediaPath });
|
||||
}
|
||||
|
||||
var viewModel = new MediaManagerFolderCreateViewModel {
|
||||
Hierarchy = _mediaLibraryService.GetMediaFolders(folderPath),
|
||||
FolderPath = folderPath
|
||||
@@ -45,12 +51,16 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost, ActionName("Create")]
|
||||
public ActionResult Create() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't create media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't create media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var viewModel = new MediaManagerFolderCreateViewModel();
|
||||
UpdateModel(viewModel);
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(viewModel.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
try {
|
||||
_mediaLibraryService.CreateFolder(viewModel.FolderPath, viewModel.Name);
|
||||
Services.Notifier.Information(T("Media folder created"));
|
||||
@@ -66,9 +76,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
}
|
||||
|
||||
public ActionResult Edit(string folderPath) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't edit media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't edit media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var viewModel = new MediaManagerFolderEditViewModel {
|
||||
FolderPath = folderPath,
|
||||
Name = folderPath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar).Last()
|
||||
@@ -80,12 +94,16 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
[HttpPost, ActionName("Edit")]
|
||||
[FormValueRequired("submit.Save")]
|
||||
public ActionResult Edit() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't edit media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't edit media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var viewModel = new MediaManagerFolderEditViewModel();
|
||||
UpdateModel(viewModel);
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(viewModel.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
try {
|
||||
_mediaLibraryService.RenameFolder(viewModel.FolderPath, viewModel.Name);
|
||||
Services.Notifier.Information(T("Media folder renamed"));
|
||||
@@ -101,12 +119,16 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
[HttpPost, ActionName("Edit")]
|
||||
[FormValueRequired("submit.Delete")]
|
||||
public ActionResult Delete() {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't delete media folder")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't delete media folder")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
var viewModel = new MediaManagerFolderEditViewModel();
|
||||
UpdateModel(viewModel);
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(viewModel.FolderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
}
|
||||
try {
|
||||
_mediaLibraryService.DeleteFolder(viewModel.FolderPath);
|
||||
Services.Notifier.Information(T("Media folder deleted"));
|
||||
@@ -122,9 +144,13 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Move(string folderPath, int[] mediaItemIds) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent, T("Couldn't move media items")))
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia, T("Couldn't move media items")))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
if (!_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
foreach (var media in Services.ContentManager.Query().ForPart<MediaPart>().ForContentItems(mediaItemIds).List()) {
|
||||
|
||||
// don't try to rename the file if there is no associated media file
|
||||
|
||||
@@ -9,12 +9,18 @@ using Orchard.MediaLibrary.ViewModels;
|
||||
using Orchard.Themes;
|
||||
using Orchard.UI.Admin;
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.MediaLibrary.Services;
|
||||
|
||||
namespace Orchard.MediaLibrary.Controllers {
|
||||
[Admin, Themed(false)]
|
||||
public class OEmbedController : Controller {
|
||||
public OEmbedController(IOrchardServices services) {
|
||||
private readonly IMediaLibraryService _mediaLibraryService;
|
||||
|
||||
public OEmbedController(
|
||||
IOrchardServices services,
|
||||
IMediaLibraryService mediaManagerService) {
|
||||
Services = services;
|
||||
_mediaLibraryService = mediaManagerService;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
@@ -32,6 +38,15 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
[ActionName("Index")]
|
||||
[ValidateInput(false)]
|
||||
public ActionResult IndexPOST(string folderPath, string url, string type, string title, string html, string thumbnail, string width, string height, string description) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
var viewModel = new OEmbedViewModel {
|
||||
Url = url,
|
||||
FolderPath = folderPath
|
||||
|
||||
@@ -13,12 +13,19 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
public class WebSearchController : Controller {
|
||||
private readonly IMediaLibraryService _mediaLibraryService;
|
||||
private readonly IContentManager _contentManager;
|
||||
|
||||
public WebSearchController(IMediaLibraryService mediaManagerService, IContentManager contentManager) {
|
||||
|
||||
public WebSearchController(
|
||||
IMediaLibraryService mediaManagerService,
|
||||
IContentManager contentManager,
|
||||
IOrchardServices orchardServices) {
|
||||
_mediaLibraryService = mediaManagerService;
|
||||
_contentManager = contentManager;
|
||||
|
||||
Services = orchardServices;
|
||||
}
|
||||
|
||||
public IOrchardServices Services { get; set; }
|
||||
|
||||
public ActionResult Index(string folderPath, string type) {
|
||||
var viewModel = new ImportMediaViewModel {
|
||||
FolderPath = folderPath,
|
||||
@@ -30,7 +37,15 @@ namespace Orchard.MediaLibrary.Controllers {
|
||||
|
||||
|
||||
[HttpPost]
|
||||
public JsonResult ImagePost(string folderPath, string type, string url) {
|
||||
public ActionResult ImagePost(string folderPath, string type, string url) {
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageOwnMedia))
|
||||
return new HttpUnauthorizedResult();
|
||||
|
||||
// Check permission.
|
||||
var rootMediaFolder = _mediaLibraryService.GetRootMediaFolder();
|
||||
if (!Services.Authorizer.Authorize(Permissions.ManageMediaContent) && !_mediaLibraryService.CanManageMediaFolder(folderPath)) {
|
||||
return new HttpUnauthorizedResult();
|
||||
}
|
||||
|
||||
try {
|
||||
var buffer = new WebClient().DownloadData(url);
|
||||
|
||||
@@ -174,6 +174,7 @@
|
||||
<Compile Include="Providers\OEmbedMenu.cs" />
|
||||
<Compile Include="Providers\WebSearchMenu.cs" />
|
||||
<Compile Include="ResourceManifest.cs" />
|
||||
<Compile Include="Security\MediaAuthorizationEventHandler.cs" />
|
||||
<Compile Include="Services\IMediaLibraryService.cs" />
|
||||
<Compile Include="Services\MediaLibraryService.cs" />
|
||||
<Compile Include="Services\Shapes.cs" />
|
||||
|
||||
@@ -4,13 +4,15 @@ using Orchard.Security.Permissions;
|
||||
|
||||
namespace Orchard.MediaLibrary {
|
||||
public class Permissions : IPermissionProvider {
|
||||
public static readonly Permission ManageMediaContent = new Permission { Description = "Managing Media", Name = "ManageMediaContent" };
|
||||
public static readonly Permission ManageMediaContent = new Permission { Description = "Manage Media", Name = "ManageMediaContent" };
|
||||
public static readonly Permission ManageOwnMedia = new Permission { Description = "Manage Own Media", Name = "ManageOwnMedia", ImpliedBy = new[] { ManageMediaContent } };
|
||||
|
||||
public virtual Feature Feature { get; set; }
|
||||
|
||||
public IEnumerable<Permission> GetPermissions() {
|
||||
return new[] {
|
||||
ManageMediaContent,
|
||||
ManageOwnMedia,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -33,6 +35,7 @@ namespace Orchard.MediaLibrary {
|
||||
},
|
||||
new PermissionStereotype {
|
||||
Name = "Contributor",
|
||||
Permissions = new[] {ManageOwnMedia}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary.Providers {
|
||||
builder.AddImageSet("clientstorage")
|
||||
.Add(T("My Computer"), "5",
|
||||
menu => menu.Action("Index", "ClientStorage", new { area = "Orchard.MediaLibrary" })
|
||||
.Permission(Permissions.ManageMediaContent));
|
||||
.Permission(Permissions.ManageOwnMedia));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary.Providers {
|
||||
builder.AddImageSet("oembed")
|
||||
.Add(T("Media Url"), "10",
|
||||
menu => menu.Action("Index", "OEmbed", new { area = "Orchard.MediaLibrary" })
|
||||
.Permission(Permissions.ManageMediaContent));
|
||||
.Permission(Permissions.ManageOwnMedia));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace Orchard.MediaLibrary.Providers {
|
||||
builder.AddImageSet("websearch")
|
||||
.Add(T("Web Search"), "7",
|
||||
menu => menu.Action("Index", "WebSearch", new { area = "Orchard.MediaLibrary" })
|
||||
.Permission(Permissions.ManageMediaContent));
|
||||
.Permission(Permissions.ManageOwnMedia));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using Orchard.ContentManagement;
|
||||
using Orchard.MediaLibrary.Models;
|
||||
using Orchard.MediaLibrary.Services;
|
||||
using Orchard.Security;
|
||||
|
||||
namespace Orchard.MediaLibrary.Security {
|
||||
public class MediaAuthorizationEventHandler : IAuthorizationServiceEventHandler {
|
||||
private readonly IAuthorizer _authorizer;
|
||||
private readonly IMediaLibraryService _mediaLibraryService;
|
||||
|
||||
public MediaAuthorizationEventHandler(
|
||||
IAuthorizer authorizer,
|
||||
IMediaLibraryService mediaLibraryService) {
|
||||
_authorizer = authorizer;
|
||||
_mediaLibraryService = mediaLibraryService;
|
||||
}
|
||||
|
||||
public void Checking(CheckAccessContext context) { }
|
||||
public void Complete(CheckAccessContext context) { }
|
||||
|
||||
public void Adjust(CheckAccessContext context) {
|
||||
var mediaPart = context.Content.As<MediaPart>();
|
||||
if (mediaPart != null) {
|
||||
if(_authorizer.Authorize(Permissions.ManageMediaContent)) {
|
||||
context.Granted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if(_authorizer.Authorize(Permissions.ManageOwnMedia)) {
|
||||
context.Granted = _mediaLibraryService.CanManageMediaFolder(mediaPart.FolderPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Web;
|
||||
using Orchard.ContentManagement;
|
||||
@@ -36,7 +37,7 @@ namespace Orchard.MediaLibrary.Services {
|
||||
/// <returns>The public URL for the media.</returns>
|
||||
string GetMediaPublicUrl(string mediaPath, string fileName);
|
||||
|
||||
MediaFolder GetRootMediaFolder();
|
||||
IMediaFolder GetRootMediaFolder();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the media folders within a given relative path.
|
||||
@@ -131,4 +132,30 @@ namespace Orchard.MediaLibrary.Services {
|
||||
/// <returns>The path to the uploaded file.</returns>
|
||||
string UploadMediaFile(string folderPath, string fileName, Stream inputStream);
|
||||
}
|
||||
|
||||
public static class MediaLibrayServiceExtensions {
|
||||
public static bool CanManageMediaFolder(this IMediaLibraryService service, string folderPath) {
|
||||
// The current user can manage a media if he has access to the whole hierarchy
|
||||
// or the media is under his personal storage folder.
|
||||
|
||||
var rootMediaFolder = service.GetRootMediaFolder();
|
||||
if (rootMediaFolder == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
var mediaPath = folderPath + "\\";
|
||||
var rootPath = rootMediaFolder.MediaPath + "\\";
|
||||
|
||||
return mediaPath.StartsWith(rootPath, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static string GetRootedFolderPath(this IMediaLibraryService service, string folderPath) {
|
||||
var rootMediaFolder = service.GetRootMediaFolder();
|
||||
if (rootMediaFolder != null) {
|
||||
return Path.Combine(rootMediaFolder.MediaPath, folderPath ?? "");
|
||||
}
|
||||
|
||||
return folderPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,7 +210,21 @@ namespace Orchard.MediaLibrary.Services {
|
||||
return GetPublicUrl(Path.Combine(mediaPath, fileName));
|
||||
}
|
||||
|
||||
public MediaFolder GetRootMediaFolder() {
|
||||
public IMediaFolder GetRootMediaFolder() {
|
||||
if (_orchardServices.Authorizer.Authorize(Permissions.ManageMediaContent)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_orchardServices.Authorizer.Authorize(Permissions.ManageOwnMedia)) {
|
||||
var currentUser = _orchardServices.WorkContext.CurrentUser;
|
||||
var userPath = _storageProvider.Combine("Users", currentUser.UserName);
|
||||
|
||||
return new MediaFolder() {
|
||||
Name = currentUser.UserName,
|
||||
MediaPath = userPath
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Orchard.MediaLibrary.Services {
|
||||
UrlHelper url) {
|
||||
|
||||
var user = _membershipService.ValidateUser(userName, password);
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMediaContent, user, null)) {
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageOwnMedia, user, null)) {
|
||||
throw new OrchardCoreException(T("Access denied"));
|
||||
}
|
||||
|
||||
@@ -72,6 +72,11 @@ namespace Orchard.MediaLibrary.Services {
|
||||
directoryName = "media";
|
||||
}
|
||||
|
||||
// If the user only has access to his own folder, rewrite the folder name
|
||||
if (!_authorizationService.TryCheckAccess(Permissions.ManageMediaContent, user, null)) {
|
||||
directoryName = Path.Combine(_mediaLibraryService.GetRootedFolderPath(directoryName));
|
||||
}
|
||||
|
||||
try {
|
||||
// delete the file if it already exists, e.g. an updated image in a blog post
|
||||
// it's safe to delete the file as each content item gets a specific folder
|
||||
|
||||
@@ -112,7 +112,7 @@ var mediaLibrarySettings = {
|
||||
<div class="media-library-folder-title" data-bind="click: folderClicked, attr: { 'data-media-path': folderPath() }, css: {selected: isSelected()}">
|
||||
<a href="#" class="media-library-navigation-folder-link"><i data-bind=" css: {'icon-folder-open-alt': isExpanded(), 'icon-folder-close-alt': !isExpanded()}"></i><span data-bind=" text: name"></span></a>
|
||||
</div>
|
||||
<ul data-bind="template: { name: 'media-folder-template', foreach: childFolders, afterRender: afterRenderMediaFolderTemplate}, visible: isExpanded()">
|
||||
<ul data-bind="template: { name: 'media-folder-template', foreach: childFolders, afterRender: afterRenderMediaFolderTemplate}, visible: isExpanded()">
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
<div class="breadCrumbs">
|
||||
<p>@Html.ActionLink(T("Media Library").ToString(), "Index", "Admin", new { area = "Orchard.MediaLibrary" }, new {}) >
|
||||
@if (Model.FolderPath != null) {
|
||||
foreach (var folder in Model.FolderPath.Split('/')) {
|
||||
if (!String.IsNullOrEmpty(folder)) {
|
||||
@Html.ActionLink(folder, "Edit", new {folderPath = folder})
|
||||
<text>></text>
|
||||
var fullPath = "";
|
||||
foreach (var folder in Model.FolderPath.Split(new[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar })) {
|
||||
if (!String.IsNullOrEmpty(folder)) {
|
||||
fullPath = Path.Combine(fullPath, folder);
|
||||
@Html.ActionLink(folder, "Index", "Admin", new {folderPath = fullPath }, null)
|
||||
<text>></text>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Orchard.MediaProcessing.Services {
|
||||
}
|
||||
|
||||
private IDictionary<string, string> GetProfileCache(string profile) {
|
||||
return _cacheManager.Get("MediaProcessing_" + profile, ctx => {
|
||||
return _cacheManager.Get("MediaProcessing_" + profile, true, ctx => {
|
||||
ctx.Monitor(_signals.When("MediaProcessing_Saved_" + profile));
|
||||
var dictionary = new Dictionary<string, string>();
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Orchard.MediaProcessing.Services {
|
||||
|
||||
public ImageProfilePart GetImageProfileByName(string name) {
|
||||
|
||||
var profileId = _cacheManager.Get("ProfileId_" + name, ctx => {
|
||||
var profileId = _cacheManager.Get("ProfileId_" + name, true, ctx => {
|
||||
var profile = _contentManager.Query<ImageProfilePart, ImageProfilePartRecord>()
|
||||
.Where(x => x.Name == name)
|
||||
.Slice(0, 1)
|
||||
|
||||
@@ -461,7 +461,7 @@ namespace Orchard.OutputCache.Filters {
|
||||
|
||||
private CacheSettings CacheSettings {
|
||||
get {
|
||||
return _cacheSettings ?? (_cacheSettings = _cacheManager.Get(CacheSettings.CacheKey, context => {
|
||||
return _cacheSettings ?? (_cacheSettings = _cacheManager.Get(CacheSettings.CacheKey, true, context => {
|
||||
context.Monitor(_signals.When(CacheSettings.CacheKey));
|
||||
return new CacheSettings(_workContext.CurrentSite.As<CacheSettingsPart>());
|
||||
}));
|
||||
|
||||
@@ -99,7 +99,7 @@ namespace Orchard.OutputCache.Services {
|
||||
}
|
||||
|
||||
public IEnumerable<CacheRouteConfig> GetRouteConfigs() {
|
||||
return _cacheManager.Get(RouteConfigsCacheKey,
|
||||
return _cacheManager.Get(RouteConfigsCacheKey, true,
|
||||
ctx => {
|
||||
ctx.Monitor(_signals.When(RouteConfigsCacheKey));
|
||||
return _repository.Fetch(c => true).Select(c => new CacheRouteConfig { RouteKey = c.RouteKey, Duration = c.Duration, GraceTime = c.GraceTime }).ToReadOnlyCollection();
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Orchard.Scripting.Dlr.Services {
|
||||
}
|
||||
|
||||
public object Evaluate(string expression, IEnumerable<IGlobalMethodProvider> providers) {
|
||||
object execContextType = _cacheManager.Get("---", ctx => (object)_scriptingManager.ExecuteExpression(@"
|
||||
object execContextType = _cacheManager.Get("---", true, ctx => (object)_scriptingManager.ExecuteExpression(@"
|
||||
class ExecBlock
|
||||
def initialize(callbacks)
|
||||
@callbacks = callbacks
|
||||
@@ -38,7 +38,7 @@ class ExecContext
|
||||
end
|
||||
ExecContext
|
||||
"));
|
||||
var ops = _cacheManager.Get("----", ctx => (ObjectOperations)_scriptingManager.ExecuteOperation(x => x));
|
||||
var ops = _cacheManager.Get("----", true, ctx => (ObjectOperations)_scriptingManager.ExecuteOperation(x => x));
|
||||
object execContext = _cacheManager.Get(expression, ctx => (object)ops.InvokeMember(execContextType, "alloc", expression));
|
||||
dynamic result = ops.InvokeMember(execContext, "evaluate", new CallbackApi(this, providers));
|
||||
return ConvertRubyValue(result);
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Orchard.Scripting {
|
||||
public Localizer T { get; set; }
|
||||
|
||||
public object Evaluate(string expression, IEnumerable<IGlobalMethodProvider> providers) {
|
||||
var expr = _cacheManager.Get(expression, ctx => {
|
||||
var expr = _cacheManager.Get(expression, true, ctx => {
|
||||
var ast = ParseExpression(expression);
|
||||
return new { Tree = ast, Errors = ast.GetErrors().ToList() };
|
||||
});
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace Orchard.Search.Controllers {
|
||||
// ignore search results which content item has been removed or unpublished
|
||||
var foundItems = _contentManager.GetMany<IContent>(foundIds, VersionOptions.Published, new QueryHints()).ToList();
|
||||
foreach (var contentItem in foundItems) {
|
||||
list.Add(_contentManager.BuildDisplay(contentItem, "Summary"));
|
||||
list.Add(_contentManager.BuildDisplay(contentItem, searchSettingPart.DisplayType));
|
||||
}
|
||||
searchHits.TotalItemCount -= foundIds.Count() - foundItems.Count();
|
||||
|
||||
|
||||
@@ -34,11 +34,14 @@ namespace Orchard.Search.Drivers {
|
||||
var model = new SearchSettingsViewModel();
|
||||
var searchFields = part.SearchFields;
|
||||
|
||||
model.DisplayType = part.DisplayType;
|
||||
|
||||
if (updater != null) {
|
||||
if (updater.TryUpdateModel(model, Prefix, null, null)) {
|
||||
part.SearchIndex = model.SelectedIndex;
|
||||
part.SearchFields = model.Entries.ToDictionary(x => x.Index, x => x.Fields.Where(e => e.Selected).Select(e => e.Field).ToArray());
|
||||
part.FilterCulture = model.FilterCulture;
|
||||
part.DisplayType = model.DisplayType;
|
||||
}
|
||||
}
|
||||
else if (_indexManager.HasIndexProvider()) {
|
||||
|
||||
@@ -24,5 +24,10 @@ namespace Orchard.Search.Models {
|
||||
get { return this.Retrieve(x => x.SearchIndex); }
|
||||
set { this.Store(x => x.SearchIndex, value); }
|
||||
}
|
||||
|
||||
public string DisplayType {
|
||||
get { return this.Retrieve(x => x.DisplayType, "Summary"); }
|
||||
set { this.Store(x => x.DisplayType, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Orchard.Search.ViewModels {
|
||||
public string SelectedIndex { get; set; }
|
||||
public IList<IndexSettingsEntry> Entries { get; set; }
|
||||
public bool FilterCulture { get; set; }
|
||||
public string DisplayType { get; set; }
|
||||
}
|
||||
|
||||
public class IndexSettingsEntry {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user