Fixes auth with AllowsCultureVariation and LanguageController post methods, fixes merge issues with navigation.controller

This commit is contained in:
Shannon
2018-05-10 19:16:46 +10:00
parent 573b8a0701
commit 68f0a64136
10 changed files with 192 additions and 203 deletions

View File

@@ -26,9 +26,9 @@
function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
/** internal method process the saving of data and post processing the result */
function saveContentItem(content, action, files, restApiUrl) {
function saveContentItem(content, action, files, restApiUrl) {
return umbRequestHelper.postSaveContent({
restApiUrl: restApiUrl,
restApiUrl: restApiUrl,
content: content,
action: action,
files: files,
@@ -40,32 +40,40 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
return {
allowsCultureVariation: function () {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"AllowsCultureVariation")),
'Failed to retrieve variant content types');
},
savePermissions: function (saveModel) {
if (!saveModel) {
throw "saveModel cannot be null";
}
if (!saveModel.contentId) {
throw "saveModel.contentId cannot be null";
}
if (!saveModel.permissions) {
throw "saveModel.permissions cannot be null";
}
savePermissions: function (saveModel) {
if (!saveModel) {
throw "saveModel cannot be null";
}
if (!saveModel.contentId) {
throw "saveModel.contentId cannot be null";
}
if (!saveModel.permissions) {
throw "saveModel.permissions cannot be null";
}
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostSaveUserGroupPermissions"),
saveModel),
'Failed to save permissions');
},
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostSaveUserGroupPermissions"),
saveModel),
'Failed to save permissions');
},
getRecycleBin: function () {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetRecycleBin")),
'Failed to retrieve data for content recycle bin');
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetRecycleBin")),
'Failed to retrieve data for content recycle bin');
},
/**
@@ -102,12 +110,12 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
}
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostSort"),
{
parentId: args.parentId,
idSortOrder: args.sortedIds
}),
'Failed to sort content');
$http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostSort"),
{
parentId: args.parentId,
idSortOrder: args.sortedIds
}),
'Failed to sort content');
},
/**
@@ -145,12 +153,12 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
}
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostMove"),
{
parentId: args.parentId,
id: args.id
}),
'Failed to move content');
$http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostMove"),
{
parentId: args.parentId,
id: args.id
}),
'Failed to move content');
},
/**
@@ -189,9 +197,9 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
}
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostCopy"),
args),
'Failed to copy content');
$http.post(umbRequestHelper.getApiUrl("contentApiBaseUrl", "PostCopy"),
args),
'Failed to copy content');
},
/**
@@ -225,12 +233,12 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
}
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostUnPublish",
{ id: id, culture: culture })),
'Failed to publish content with id ' + id);
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostUnPublish",
{ id: id, culture: culture })),
'Failed to publish content with id ' + id);
},
/**
* @ngdoc method
@@ -253,11 +261,11 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
*/
emptyRecycleBin: function () {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"EmptyRecycleBin")),
'Failed to empty the recycle bin');
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"EmptyRecycleBin")),
'Failed to empty the recycle bin');
},
/**
@@ -282,22 +290,22 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
*/
deleteById: function (id) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"DeleteById",
[{ id: id }])),
'Failed to delete item ' + id);
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"DeleteById",
[{ id: id }])),
'Failed to delete item ' + id);
},
deleteBlueprint: function (id) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"DeleteBlueprint",
[{ id: id }])),
'Failed to delete blueprint ' + id);
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"DeleteBlueprint",
[{ id: id }])),
'Failed to delete blueprint ' + id);
},
/**
@@ -324,22 +332,22 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
*/
getById: function (id, culture) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetById",
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetById",
{ id: id, culture: culture })),
'Failed to retrieve data for content id ' + id);
'Failed to retrieve data for content id ' + id);
},
getBlueprintById: function (id) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetBlueprintById",
[{ id: id }])),
'Failed to retrieve data for content id ' + id);
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetBlueprintById",
[{ id: id }])),
'Failed to retrieve data for content id ' + id);
},
/**
@@ -371,12 +379,12 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
});
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetByIds",
idQuery)),
'Failed to retrieve data for content with multiple ids');
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetByIds",
idQuery)),
'Failed to retrieve data for content with multiple ids');
},
@@ -415,23 +423,23 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
getScaffold: function (parentId, alias) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetEmpty",
[{ contentTypeAlias: alias }, { parentId: parentId }])),
'Failed to retrieve data for empty content item type ' + alias);
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetEmpty",
[{ contentTypeAlias: alias }, { parentId: parentId }])),
'Failed to retrieve data for empty content item type ' + alias);
},
getBlueprintScaffold: function (parentId, blueprintId) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetEmpty",
[{ blueprintId: blueprintId }, { parentId: parentId}])),
'Failed to retrieve blueprint for id ' + blueprintId);
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetEmpty",
[{ blueprintId: blueprintId }, { parentId: parentId }])),
'Failed to retrieve blueprint for id ' + blueprintId);
},
/**
@@ -456,11 +464,11 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
*/
getNiceUrl: function (id) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetNiceUrl", [{ id: id }])),
'Failed to retrieve url for id:' + id);
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetNiceUrl", [{ id: id }])),
'Failed to retrieve url for id:' + id);
},
/**
@@ -572,21 +580,21 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
*/
checkPermission: function (permission, id) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"HasPermission",
[{ permissionToCheck: permission }, { nodeId: id }])),
'Failed to check permission for item ' + id);
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"HasPermission",
[{ permissionToCheck: permission }, { nodeId: id }])),
'Failed to check permission for item ' + id);
},
getDetailedPermissions: function (contentId) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetDetailedPermissions", { contentId: contentId })),
'Failed to retrieve permissions for content item ' + contentId);
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"GetDetailedPermissions", { contentId: contentId })),
'Failed to retrieve permissions for content item ' + contentId);
},
getPermissions: function (nodeIds) {
@@ -628,17 +636,17 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
*
*/
save: function (content, isNew, files) {
var endpoint = umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostSave");
return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint);
var endpoint = umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostSave");
return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint);
},
saveBlueprint: function (content, isNew, files) {
var endpoint = umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostSaveBlueprint");
return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint);
var endpoint = umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostSaveBlueprint");
return saveContentItem(content, "save" + (isNew ? "New" : ""), files, endpoint);
},
/**
@@ -670,10 +678,10 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
*
*/
publish: function (content, isNew, files) {
var endpoint = umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostSave");
return saveContentItem(content, "publish" + (isNew ? "New" : ""), files, endpoint);
var endpoint = umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostSave");
return saveContentItem(content, "publish" + (isNew ? "New" : ""), files, endpoint);
},
@@ -704,10 +712,10 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
*
*/
sendToPublish: function (content, isNew, files) {
var endpoint = umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostSave");
return saveContentItem(content, "sendPublish" + (isNew ? "New" : ""), files, endpoint);
var endpoint = umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostSave");
return saveContentItem(content, "sendPublish" + (isNew ? "New" : ""), files, endpoint);
},
/**
@@ -737,12 +745,12 @@ function contentResource($q, $http, umbDataFormatter, umbRequestHelper) {
}
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostPublishById",
[{ id: id }])),
'Failed to publish content with id ' + id);
$http.post(
umbRequestHelper.getApiUrl(
"contentApiBaseUrl",
"PostPublishById",
[{ id: id }])),
'Failed to publish content with id ' + id);
},

View File

@@ -166,15 +166,6 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
'Failed to retrieve all content types');
},
allowsVariation: function() {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"contentTypeApiBaseUrl",
"AllowsVariation")),
'Failed to retrieve variant content types');
},
getScaffold: function (parentId) {
return umbRequestHelper.resourcePromise(

View File

@@ -7,10 +7,6 @@ function contentTypeHelper(contentTypeResource, dataTypeResource, $filter, $inje
var contentTypeHelperService = {
allowsVariation: function() {
return contentTypeResource.allowsVariation();
},
createIdArray: function(array) {
var newArray = [];

View File

@@ -9,7 +9,7 @@
*
* @param {navigationService} navigationService A reference to the navigationService
*/
function NavigationController($scope, $rootScope, $location, $log, $q, $routeParams, $timeout, treeService, appState, navigationService, keyboardService, dialogService, historyService, eventsService, sectionResource, angularHelper, languageResource, contentTypeHelper) {
function NavigationController($scope, $rootScope, $location, $log, $q, $routeParams, $timeout, treeService, appState, navigationService, keyboardService, dialogService, historyService, eventsService, sectionResource, angularHelper, languageResource, contentResource) {
//this is used to trigger the tree to start loading once everything is ready
var treeInitPromise = $q.defer();
@@ -209,47 +209,18 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
$scope.showSearchResults = args.value;
}
//load languages if doc types allow variations
if ($scope.currentSection === "content") {
contentTypeHelper.allowsVariation().then(function (b) {
if (b === "true") {
//load languages if there are more than 1
loadLanguages();
} else {
$scope.languages = [];
init();
}
});
}
}));
// Listen for language updates
evts.push(eventsService.on("editors.languages.languageDeleted", function (e, args) {
languageResource.getAll().then(function (languages) {
contentTypeHelper.allowsVariation().then(function (b) {
if (b === "true") {
$scope.languages = languages;
} else {
$scope.languages = [];
}
});
loadLanguages().then(function (languages) {
$scope.languages = languages;
});
}));
evts.push(eventsService.on("editors.languages.languageCreated", function (e, args) {
languageResource.getAll().then(function (languages) {
contentTypeHelper.allowsVariation().then(function (b) {
if (b === "true") {
$scope.languages = languages;
} else {
$scope.languages = [];
}
});
loadLanguages().then(function (languages) {
$scope.languages = languages;
});
}));
@@ -341,12 +312,26 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
});
}
/**
* This loads the language data, if the are no variant content types configured this will return no languages
*/
function loadLanguages() {
return contentResource.allowsCultureVariation().then(function (b) {
if (b === "true") {
return languageResource.getAll()
} else {
return $q.when([]); //resolve an empty collection
}
});
}
/**
* Called once during init to initialize the navigation/tree/languages
*/
function initNav() {
// load languages
languageResource.getAll().then(function (languages) {
loadLanguages().then(function (languages) {
$scope.languages = languages;
@@ -398,7 +383,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
$scope.selectLanguage = function (language) {
$location.search("mculture", language.culture);
// close the language selector
$scope.page.languageSelectorIsOpen = false;

View File

@@ -64,6 +64,18 @@ namespace Umbraco.Web.Editors
new ParameterSwapControllerActionSelector.ParameterSwapInfo("GetNiceUrl", "id", typeof(int), typeof(Guid), typeof(Udi))));
}
}
/// <summary>
/// Returns true if any content types have culture variation enabled
/// </summary>
/// <returns></returns>
[HttpGet]
[WebApi.UmbracoAuthorize, OverrideAuthorization]
public bool AllowsCultureVariation()
{
var contentTypes = Services.ContentTypeService.GetAll();
return contentTypes.Any(contentType => contentType.Variations.HasAny(ContentVariation.CultureNeutral | ContentVariation.CultureSegment));
}
/// <summary>
/// Return content for the specified ids

View File

@@ -35,12 +35,6 @@ namespace Umbraco.Web.Editors
{
return Services.ContentTypeService.Count();
}
[HttpGet]
public bool AllowsVariation()
{
var contentTypes = Services.ContentTypeService.GetAll();
return contentTypes.Any(contentType => contentType.Variations.HasFlag(ContentVariation.CultureNeutral));
}
public DocumentTypeDisplay GetById(int id)
{

View File

@@ -12,6 +12,7 @@ using Umbraco.Core.Persistence;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
using Umbraco.Web.WebApi.Filters;
using Language = Umbraco.Web.Models.ContentEditing.Language;
namespace Umbraco.Web.Editors
@@ -81,6 +82,7 @@ namespace Umbraco.Web.Editors
/// <summary>
/// Deletes a language with a given ID
/// </summary>
[UmbracoTreeAuthorize(Core.Constants.Trees.Languages)]
[HttpDelete]
[HttpPost]
public IHttpActionResult DeleteLanguage(int id)
@@ -104,6 +106,7 @@ namespace Umbraco.Web.Editors
/// <summary>
/// Creates or saves a language
/// </summary>
[UmbracoTreeAuthorize(Core.Constants.Trees.Languages)]
[HttpPost]
public Language SaveLanguage(Language language)
{

View File

@@ -257,24 +257,22 @@ namespace Umbraco.Web.Trees
return;
}
if (entity is IDocumentEntitySlim docEntity)
if (!(entity is IDocumentEntitySlim docEntity))
throw new InvalidOperationException($"Cannot render a tree node for a culture when the entity isn't {typeof(IDocumentEntitySlim)}, instead it is {entity.GetType()}");
// we are getting the tree for a given culture,
// for those items that DO support cultures, we need to get the proper name, IF it exists
// otherwise, invariant is fine
if (docEntity.Variations.Has(Core.Models.ContentVariation.CultureNeutral) &&
docEntity.CultureNames.TryGetValue(culture, out var name) &&
!string.IsNullOrWhiteSpace(name))
{
// we are getting the tree for a given culture,
// for those items that DO support cultures, we need to get the proper name, IF it exists
// otherwise, invariant is fine
if (docEntity.Variations.Has(Core.Models.ContentVariation.CultureNeutral) &&
docEntity.CultureNames.TryGetValue(culture, out var name) &&
!string.IsNullOrWhiteSpace(name))
{
entity.Name = name;
}
if (string.IsNullOrWhiteSpace(entity.Name))
entity.Name = "[[" + entity.Id + "]]";
entity.Name = name;
}
throw new InvalidOperationException($"Cannot render a tree node for a culture when the entity isn't {typeof(IDocumentEntitySlim)}, instead it is {entity.GetType()}");
if (string.IsNullOrWhiteSpace(entity.Name))
entity.Name = "[[" + entity.Id + "]]";
}
private void AddActionNode<TAction>(IUmbracoEntity item, MenuItemCollection menu, bool hasSeparator = false, bool convert = false)

View File

@@ -11,6 +11,6 @@ namespace Umbraco.Web.WebApi.Filters
[AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public sealed class EnableOverrideAuthorizationAttribute : Attribute
{
//TODO: Can we remove this and use the System.Web.Http.OverrideAuthorizationAttribute which uses IOverrideFilter instead?
//fixme we should remove this and use the System.Web.Http.OverrideAuthorizationAttribute which uses IOverrideFilter instead
}
}

View File

@@ -5,6 +5,8 @@ using System.Web.Http.Controllers;
namespace Umbraco.Web.WebApi.Filters
{
//fixme remove this since we don't need it, see notes in EnableOverrideAuthorizationAttribute
/// <summary>
/// Abstract auth filter class that can be used to enable overriding class auth filters at the action level
/// </summary>