Changes UserController to be CurrentUserController - and removes the other methods in there since that was an overlooked security issue. This controller is responsible solely for dealing with the currently logged in user. Changes over to be currentuser.resource as well.

This commit is contained in:
Shannon
2013-11-12 18:07:10 +11:00
parent a532b49485
commit 5f5f535f05
6 changed files with 146 additions and 231 deletions

View File

@@ -0,0 +1,53 @@
/**
* @ngdoc service
* @name umbraco.resources.currentUserResource
* @description Used for read/updates for the currently logged in user
*
*
**/
function currentUserResource($q, $http, umbRequestHelper) {
//the factory object returned
return {
/**
* @ngdoc method
* @name umbraco.resources.currentUserResource#changePassword
* @methodOf umbraco.resources.currentUserResource
*
* @description
* Changes the current users password
*
* @returns {Promise} resourcePromise object containing the user array.
*
*/
changePassword: function (changePasswordArgs) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"currentUserApiBaseUrl",
"PostChangePassword"),
changePasswordArgs),
'Failed to change password');
},
/**
* @ngdoc method
* @name umbraco.resources.currentUserResource#getMembershipProviderConfig
* @methodOf umbraco.resources.currentUserResource
*
* @description
* Gets the configuration of the user membership provider which is used to configure the change password form
*/
getMembershipProviderConfig: function () {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"currentUserApiBaseUrl",
"GetMembershipProviderConfig")),
'Failed to retreive membership provider config');
},
};
}
angular.module('umbraco.resources').factory('currentUserResource', currentUserResource);

View File

@@ -1,113 +0,0 @@
/**
* @ngdoc service
* @name umbraco.resources.userResource
* @description Retrives user data from the server, cannot be used for authentication, for this, use the user.service
*
*
**/
function userResource($q, $http, umbRequestHelper) {
//the factory object returned
return {
/**
* @ngdoc method
* @name umbraco.resources.userResource#getById
* @methodOf umbraco.resources.userResource
*
* @description
* Gets a user with a given id
*
* ##usage
* <pre>
* userResource.getById(1234)
* .then(function(ent) {
* var myUser = ent;
* alert('im here!');
* });
* </pre>
*
* @param {Int} id id of user to return
* @returns {Promise} resourcePromise object containing the user.
*
*/
getById: function (id) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"userApiBaseUrl",
"GetById",
[{ id: id }])),
'Failed to retreive user data for id ' + id);
},
/**
* @ngdoc method
* @name umbraco.resources.userResource#getAll
* @methodOf umbraco.resources.userResource
*
* @description
* Gets all users available on the system
*
* ##usage
* <pre>
* contentResource.getAll()
* .then(function(userArray) {
* var myUsers = userArray;
* alert('they are here!');
* });
* </pre>
*
* @returns {Promise} resourcePromise object containing the user array.
*
*/
getAll: function () {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"userApiBaseUrl",
"GetAll")),
'Failed to retreive all users');
},
/**
* @ngdoc method
* @name umbraco.resources.userResource#changePassword
* @methodOf umbraco.resources.userResource
*
* @description
* Changes the current users password
*
* @returns {Promise} resourcePromise object containing the user array.
*
*/
changePassword: function (changePasswordArgs) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"userApiBaseUrl",
"PostChangePassword"),
changePasswordArgs),
'Failed to change password');
},
/**
* @ngdoc method
* @name umbraco.resources.userResource#getMembershipProviderConfig
* @methodOf umbraco.resources.userResource
*
* @description
* Gets the configuration of the user membership provider which is used to configure the change password form
*/
getMembershipProviderConfig: function () {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"userApiBaseUrl",
"GetMembershipProviderConfig")),
'Failed to retreive membership provider config');
},
};
}
angular.module('umbraco.resources').factory('userResource', userResource);

View File

@@ -80,7 +80,7 @@ function MediaFolderBrowserDashboardController($rootScope, $scope, assetsService
angular.module("umbraco").controller("Umbraco.Dashboard.MediaFolderBrowserDashboardController", MediaFolderBrowserDashboardController); angular.module("umbraco").controller("Umbraco.Dashboard.MediaFolderBrowserDashboardController", MediaFolderBrowserDashboardController);
function ChangePasswordDashboardController($scope, xmlhelper, $log, userResource, formHelper) { function ChangePasswordDashboardController($scope, xmlhelper, $log, currentUserResource, formHelper) {
//create the initial model for change password property editor //create the initial model for change password property editor
$scope.changePasswordModel = { $scope.changePasswordModel = {
@@ -91,7 +91,7 @@ function ChangePasswordDashboardController($scope, xmlhelper, $log, userResource
}; };
//go get the config for the membership provider and add it to the model //go get the config for the membership provider and add it to the model
userResource.getMembershipProviderConfig().then(function(data) { currentUserResource.getMembershipProviderConfig().then(function(data) {
$scope.changePasswordModel.config = data; $scope.changePasswordModel.config = data;
//ensure the hasPassword config option is set to true (the user of course has a password already assigned) //ensure the hasPassword config option is set to true (the user of course has a password already assigned)
//this will ensure the oldPassword is shown so they can change it //this will ensure the oldPassword is shown so they can change it
@@ -105,7 +105,7 @@ function ChangePasswordDashboardController($scope, xmlhelper, $log, userResource
$scope.changePassword = function() { $scope.changePassword = function() {
if (formHelper.submitForm({ scope: $scope })) { if (formHelper.submitForm({ scope: $scope })) {
userResource.changePassword($scope.changePasswordModel.value).then(function(data) { currentUserResource.changePassword($scope.changePasswordModel.value).then(function(data) {
//if the password has been reset, then update our model //if the password has been reset, then update our model
if (data.value) { if (data.value) {

View File

@@ -102,8 +102,8 @@ namespace Umbraco.Web.Editors
controller => controller.PostLogin(null, null)) controller => controller.PostLogin(null, null))
}, },
{ {
"userApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<UserController>( "currentUserApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<CurrentUserController>(
controller => controller.GetAll()) controller => controller.GetMembershipProviderConfig())
}, },
{ {
"legacyApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<LegacyController>( "legacyApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl<LegacyController>(

View File

@@ -1,112 +1,87 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Web.Http; using System.Web.Http;
using System.Web.Security; using System.Web.Security;
using AutoMapper; using AutoMapper;
using Umbraco.Core.Configuration; using Umbraco.Core.Configuration;
using Umbraco.Web.Models; using Umbraco.Web.Models;
using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Models.ContentEditing;
using Umbraco.Web.Models.Mapping; using Umbraco.Web.Models.Mapping;
using Umbraco.Web.Mvc; using Umbraco.Web.Mvc;
using Umbraco.Web.UI; using Umbraco.Web.UI;
using Umbraco.Web.WebApi; using Umbraco.Web.WebApi;
using umbraco; using umbraco;
using legacyUser = umbraco.BusinessLogic.User; using legacyUser = umbraco.BusinessLogic.User;
using System.Net.Http; using System.Net.Http;
using System.Collections.Specialized; using System.Collections.Specialized;
using Constants = Umbraco.Core.Constants; using Constants = Umbraco.Core.Constants;
namespace Umbraco.Web.Editors namespace Umbraco.Web.Editors
{ {
/// <summary> /// <summary>
/// Controller to back the User.Resource service, used for fetching user data when already authenticated. user.service is currently used for handling authentication /// Controller to back the User.Resource service, used for fetching user data when already authenticated. user.service is currently used for handling authentication
/// </summary> /// </summary>
[PluginController("UmbracoApi")] [PluginController("UmbracoApi")]
public class UserController : UmbracoAuthorizedJsonController public class CurrentUserController : UmbracoAuthorizedJsonController
{ {
/// <summary> /// <summary>
/// Returns the configuration for the backoffice user membership provider - used to configure the change password dialog /// Returns the configuration for the backoffice user membership provider - used to configure the change password dialog
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public IDictionary<string, object> GetMembershipProviderConfig() public IDictionary<string, object> GetMembershipProviderConfig()
{ {
var provider = Membership.Providers[UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider]; var provider = Membership.Providers[UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider];
if (provider == null) if (provider == null)
{ {
throw new InvalidOperationException("No back office membership provider found with the name " + UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider); throw new InvalidOperationException("No back office membership provider found with the name " + UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider);
} }
return provider.GetConfiguration(); return provider.GetConfiguration();
} }
/// <summary> /// <summary>
/// Returns a user by id /// Changes the users password
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="data"></param>
/// <returns></returns> /// <returns>
public UserDetail GetById(int id) /// If the password is being reset it will return the newly reset password, otherwise will return an empty value
{ /// </returns>
var user = Services.UserService.GetUserById(id); public ModelWithNotifications<string> PostChangePassword(ChangingPasswordModel data)
if (user == null) {
{ var userProvider = Membership.Providers[UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider];
throw new HttpResponseException(HttpStatusCode.NotFound); if (userProvider == null)
} {
throw new InvalidOperationException("No membership provider found with the name " + UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider);
}
return Mapper.Map<UserDetail>(user);
} //TODO: WE need to support this! - requires UI updates, etc...
if (userProvider.RequiresQuestionAndAnswer)
/// <summary> {
/// Changes the users password throw new NotSupportedException("Currently the user editor does not support providers that have RequiresQuestionAndAnswer specified");
/// </summary> }
/// <param name="data"></param>
/// <returns> var passwordChangeResult = Security.ChangePassword(Security.CurrentUser.Username, data, userProvider);
/// If the password is being reset it will return the newly reset password, otherwise will return an empty value if (passwordChangeResult.Success)
/// </returns> {
public ModelWithNotifications<string> PostChangePassword(ChangingPasswordModel data) //even if we weren't resetting this, it is the correct value (null), otherwise if we were resetting then it will contain the new pword
{ var result = new ModelWithNotifications<string>(passwordChangeResult.Result.ResetPassword);
var userProvider = Membership.Providers[UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider]; result.AddSuccessNotification(ui.Text("user", "password"), ui.Text("user", "passwordChanged"));
if (userProvider == null) return result;
{ }
throw new InvalidOperationException("No membership provider found with the name " + UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider);
} //it wasn't successful, so add the change error to the model state, we've name the property alias _umb_password on the form
// so that is why it is being used here.
//TODO: WE need to support this! - requires UI updates, etc... ModelState.AddPropertyError(
if (userProvider.RequiresQuestionAndAnswer) passwordChangeResult.Result.ChangeError,
{ string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
throw new NotSupportedException("Currently the user editor does not support providers that have RequiresQuestionAndAnswer specified");
} throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState));
}
var passwordChangeResult = Security.ChangePassword(Security.CurrentUser.Username, data, userProvider);
if (passwordChangeResult.Success) }
{ }
//even if we weren't resetting this, it is the correct value (null), otherwise if we were resetting then it will contain the new pword
var result = new ModelWithNotifications<string>(passwordChangeResult.Result.ResetPassword);
result.AddSuccessNotification(ui.Text("user", "password"), ui.Text("user", "passwordChanged"));
return result;
}
//it wasn't successful, so add the change error to the model state, we've name the property alias _umb_password on the form
// so that is why it is being used here.
ModelState.AddPropertyError(
passwordChangeResult.Result.ChangeError,
string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
throw new HttpResponseException(Request.CreateValidationErrorResponse(ModelState));
}
/// <summary>
/// Returns all active users
/// </summary>
/// <returns></returns>
public IEnumerable<UserBasic> GetAll()
{
return Services.UserService.GetAllUsers().Where(x => x.IsLockedOut == false).Select(Mapper.Map<UserBasic>);
}
}
}

View File

@@ -362,7 +362,7 @@
<Compile Include="Editors\EntityController.cs" /> <Compile Include="Editors\EntityController.cs" />
<Compile Include="Editors\MediaPostValidateAttribute.cs" /> <Compile Include="Editors\MediaPostValidateAttribute.cs" />
<Compile Include="Editors\MemberController.cs" /> <Compile Include="Editors\MemberController.cs" />
<Compile Include="Editors\UserController.cs" /> <Compile Include="Editors\CurrentUserController.cs" />
<Compile Include="Install\Steps\MajorUpgradeReport.cs" /> <Compile Include="Install\Steps\MajorUpgradeReport.cs" />
<Compile Include="Models\ContentEditing\DashboardControl.cs" /> <Compile Include="Models\ContentEditing\DashboardControl.cs" />
<Compile Include="Models\ContentEditing\DataTypeDisplay.cs" /> <Compile Include="Models\ContentEditing\DataTypeDisplay.cs" />