diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/user.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/user.resource.js index b0c338fa90..857ef65160 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/user.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/user.resource.js @@ -77,26 +77,17 @@ function userResource($q, $http, umbRequestHelper) { * * @description * Changes the current users password - * - * ##usage - *
- * contentResource.getAll()
- * .then(function(userArray) {
- * var myUsers = userArray;
- * alert('they are here!');
- * });
- *
*
* @returns {Promise} resourcePromise object containing the user array.
*
*/
- changePassword: function (oldPassword, newPassword) {
+ changePassword: function (changePasswordArgs) {
return umbRequestHelper.resourcePromise(
$http.post(
umbRequestHelper.getApiUrl(
"userApiBaseUrl",
"PostChangePassword"),
- { oldPassword: oldPassword, newPassword: newPassword }),
+ changePasswordArgs),
'Failed to change password');
},
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
index 28f8679d1a..4dec2c17b9 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js
@@ -4,7 +4,7 @@
* @name umbraco.services.contentEditingHelper
* @description A helper service for content/media/member controllers when editing/creating/saving content.
**/
-function contentEditingHelper($location, $routeParams, notificationsService, serverValidationManager, dialogService) {
+function contentEditingHelper($location, $routeParams, notificationsService, serverValidationManager, dialogService, formHelper) {
return {
@@ -95,60 +95,6 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
return changed;
},
- /**
- * @ngdoc method
- * @name umbraco.services.contentEditingHelper#handleValidationErrors
- * @methodOf umbraco.services.contentEditingHelper
- * @function
- *
- * @description
- * A function to handle the validation (modelState) errors collection which will happen on a 400 error indicating validation errors
- * It's worth noting that when a 400 occurs, the data is still saved just never published, though this depends on if the entity is a new
- * entity and whether or not the data fulfils the absolute basic requirements like having a mandatory Name.
- */
- handleValidationErrors: function (allProps, modelState) {
-
- //find the content property for the current error, for use in the loop below
- function findContentProp(props, propAlias) {
- return _.find(props, function (item) {
- return (item.alias === propAlias);
- });
- }
-
- for (var e in modelState) {
- //the alias in model state can be in dot notation which indicates
- // * the first part is the content property alias
- // * the second part is the field to which the valiation msg is associated with
- //There will always be at least 2 parts since all model errors for properties are prefixed with "Properties"
- var parts = e.split(".");
- if (parts.length > 1) {
- var propertyAlias = parts[1];
-
- //find the content property for the current error
- var contentProperty = findContentProp(allProps, propertyAlias);
-
- if (contentProperty) {
- //if it contains 2 '.' then we will wire it up to a property's field
- if (parts.length > 2) {
- //add an error with a reference to the field for which the validation belongs too
- serverValidationManager.addPropertyError(contentProperty.alias, parts[2], modelState[e][0]);
- }
- else {
- //add a generic error for the property, no reference to a specific field
- serverValidationManager.addPropertyError(contentProperty.alias, "", modelState[e][0]);
- }
- }
- }
- else {
- //the parts are only 1, this means its not a property but a native content property
- serverValidationManager.addFieldError(parts[0], modelState[e][0]);
- }
-
- //add to notifications
- notificationsService.error("Validation", modelState[e][0]);
- }
- },
-
/**
* @ngdoc function
* @name umbraco.services.contentEditingHelper#handleSaveError
@@ -174,7 +120,8 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
//now we need to look through all the validation errors
if (args.err.data && (args.err.data.ModelState)) {
- this.handleValidationErrors(args.allNewProps, args.err.data.ModelState);
+ //wire up the server validation errs
+ formHelper.handleServerValidation(args.err.data.ModelState);
if (!args.redirectOnFailure || !this.redirectToCreatedContent(args.err.data.id, args.err.data.ModelState)) {
//we are not redirecting because this is not new content, it is existing content. In this case
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js
index 7efc8bebaa..647f124be6 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js
@@ -7,7 +7,7 @@
* A utility class used to streamline how forms are developed, to ensure that validation is check and displayed consistently and to ensure that the correct events
* fire when they need to.
*/
-function formHelper(angularHelper, serverValidationManager, $timeout, notificationsService) {
+function formHelper(angularHelper, serverValidationManager, $timeout, notificationsService, dialogService) {
return {
/**
@@ -102,6 +102,86 @@ function formHelper(angularHelper, serverValidationManager, $timeout, notificati
}
args.scope.$broadcast("formSubmitted", { scope: args.scope });
+ },
+
+ /**
+ * @ngdoc function
+ * @name umbraco.services.formHelper#handleError
+ * @methodOf umbraco.services.formHelper
+ * @function
+ *
+ * @description
+ * Needs to be called when a form submission fails, this will wire up all server validation errors in ModelState and
+ * add the correct messages to the notifications. If a server error has occurred this will show a ysod.
+ *
+ * @param {object} err The error object returned from the http promise
+ */
+ handleError: function (err) {
+ //When the status is a 400 status with a custom header: X-Status-Reason: Validation failed, we have validation errors.
+ //Otherwise the error is probably due to invalid data (i.e. someone mucking around with the ids or something).
+ //Or, some strange server error
+ if (err.status === 400) {
+ //now we need to look through all the validation errors
+ if (err.data && (err.data.ModelState)) {
+
+ //wire up the server validation errs
+ this.handleServerValidation(err.data.ModelState);
+
+ //execute all server validation events and subscribers
+ serverValidationManager.executeAndClearAllSubscriptions();
+ }
+ else {
+ dialogService.ysodDialog(err);
+ }
+ }
+ else {
+ dialogService.ysodDialog(err);
+ }
+ },
+
+ /**
+ * @ngdoc function
+ * @name umbraco.services.formHelper#handleServerValidation
+ * @methodOf umbraco.services.formHelper
+ * @function
+ *
+ * @description
+ * This wires up all of the server validation model state so that valServer and valServerField directives work
+ *
+ * @param {object} err The error object returned from the http promise
+ */
+ handleServerValidation: function(modelState) {
+ for (var e in modelState) {
+
+ //the alias in model state can be in dot notation which indicates
+ // * the first part is the content property alias
+ // * the second part is the field to which the valiation msg is associated with
+ //There will always be at least 2 parts for properties since all model errors for properties are prefixed with "Properties"
+ //If it is not prefixed with "Properties" that means the error is for a field of the object directly.
+
+ var parts = e.split(".");
+ if (parts.length > 1) {
+ var propertyAlias = parts[1];
+
+ //if it contains 2 '.' then we will wire it up to a property's field
+ if (parts.length > 2) {
+ //add an error with a reference to the field for which the validation belongs too
+ serverValidationManager.addPropertyError(propertyAlias, parts[2], modelState[e][0]);
+ }
+ else {
+ //add a generic error for the property, no reference to a specific field
+ serverValidationManager.addPropertyError(propertyAlias, "", modelState[e][0]);
+ }
+
+ }
+ else {
+ //the parts are only 1, this means its not a property but a native content property
+ serverValidationManager.addFieldError(parts[0], modelState[e][0]);
+ }
+
+ //add to notifications
+ notificationsService.error("Validation", modelState[e][0]);
+ }
}
};
}
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js b/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js
index b8d97e374c..03f5e96ab0 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/servervalidationmgr.service.js
@@ -44,8 +44,11 @@ function serverValidationManager($timeout) {
* @function
*
* @description
- * This is primarily used for scenarios where the error collection needs to be persisted over a route change. Generally this
- * is when a content item (or any item) is created. The controller should call this method once the data is bound to the scope
+ * This method needs to be called once all field and property errors are wired up.
+ *
+ * In some scenarios where the error collection needs to be persisted over a route change
+ * (i.e. when a content item (or any item) is created and the route redirects to the editor)
+ * the controller should call this method once the data is bound to the scope
* so that any persisted validation errors are re-bound to their controls. Once they are re-binded this then clears the validation
* colleciton so that if another route change occurs, the previously persisted validation errors are not re-bound to the new item.
*/
diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/ChangePassword.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/ChangePassword.html
index 54d4827240..9d56075962 100644
--- a/src/Umbraco.Web.UI.Client/src/views/dashboard/ChangePassword.html
+++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/ChangePassword.html
@@ -1,6 +1,6 @@
diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js
index 64040362d4..b113fdf93e 100644
--- a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js
@@ -84,9 +84,10 @@ function ChangePasswordDashboardController($scope, xmlhelper, $log, userResource
//create the initial model for change password property editor
$scope.changePasswordModel = {
- alias: "password",
+ alias: "_umb_password",
view: "changepassword",
- config: {}
+ config: {},
+ value: {}
};
//go get the config for the membership provider and add it to the model
@@ -101,20 +102,18 @@ function ChangePasswordDashboardController($scope, xmlhelper, $log, userResource
////this is the model we will pass to the service
//$scope.profile = {};
- $scope.changePassword = function(p) {
+ $scope.changePassword = function() {
if (formHelper.submitForm({ scope: $scope })) {
- //userResource.changePassword(p.oldPassword, p.newPassword).then(function() {
+ userResource.changePassword($scope.changePasswordModel.value).then(function() {
- // formHelper.resetForm({ scope: $scope, notifications: data.notifications });
-
- // //TODO: This is temporary - server validation will work automatically with the val-server directives.
- // $scope.passwordForm.$setValidity(true);
- //}, function () {
- // //TODO: This is temporary - server validation will work automatically with the val-server directives.
- // //this only happens if there is a wrong oldPassword sent along
- // $scope.passwordForm.oldpass.$setValidity("oldPassword", false);
- //});
+ formHelper.resetForm({ scope: $scope, notifications: data.notifications });
+
+ }, function (err) {
+
+ formHelper.handleError(err);
+
+ });
}
};
}
diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/content-editing-helper.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/content-editing-helper.spec.js
index 2c73044d3e..1fdd7aee62 100644
--- a/src/Umbraco.Web.UI.Client/test/unit/common/services/content-editing-helper.spec.js
+++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/content-editing-helper.spec.js
@@ -1,5 +1,5 @@
describe('contentEditingHelper tests', function () {
- var contentEditingHelper, $routeParams, serverValidationManager, mocksUtils, notificationsService;
+ var contentEditingHelper, $routeParams, serverValidationManager, mocksUtils, notificationsService, formHelper;
beforeEach(module('umbraco.services'));
beforeEach(module('umbraco.mocks'));
@@ -14,6 +14,7 @@ describe('contentEditingHelper tests', function () {
serverValidationManager = $injector.get('serverValidationManager');
mocksUtils = $injector.get('mocksUtils');
notificationsService = $injector.get('notificationsService');
+ formHelper = $injector.get('formHelper');
}));
describe('handles http validation errors', function () {
@@ -88,7 +89,7 @@ describe('contentEditingHelper tests', function () {
var allProps = contentEditingHelper.getAllProps(content);
//act
- contentEditingHelper.handleValidationErrors(allProps, { Name: ["Required"] });
+ formHelper.handleServerValidation({ Name: ["Required"] });
//assert
expect(serverValidationManager.items.length).toBe(1);
@@ -104,7 +105,7 @@ describe('contentEditingHelper tests', function () {
var allProps = contentEditingHelper.getAllProps(content);
//act
- contentEditingHelper.handleValidationErrors(allProps, { "Property.bodyText": ["Required"] });
+ formHelper.handleServerValidation({ "Property.bodyText": ["Required"] });
//assert
expect(serverValidationManager.items.length).toBe(1);
@@ -120,7 +121,7 @@ describe('contentEditingHelper tests', function () {
var allProps = contentEditingHelper.getAllProps(content);
//act
- contentEditingHelper.handleValidationErrors(allProps, { "Property.bodyText.value": ["Required"] });
+ formHelper.handleServerValidation({ "Property.bodyText.value": ["Required"] });
//assert
expect(serverValidationManager.items.length).toBe(1);
@@ -136,8 +137,7 @@ describe('contentEditingHelper tests', function () {
var allProps = contentEditingHelper.getAllProps(content);
//act
- contentEditingHelper.handleValidationErrors(
- allProps,
+ formHelper.handleServerValidation(
{
"Name": ["Required"],
"UpdateDate": ["Invalid date"],
diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs
index fb36cfeca6..bd8895d3a0 100644
--- a/src/Umbraco.Web/Editors/MemberController.cs
+++ b/src/Umbraco.Web/Editors/MemberController.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
+using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
@@ -250,132 +251,18 @@ namespace Umbraco.Web.Editors
//password changes ?
if (contentItem.Password == null) return null;
- //Are we resetting the password??
- if (contentItem.Password.Reset.HasValue && contentItem.Password.Reset.Value)
+ var passwordChangeResult = Security.ChangePassword(membershipUser.UserName, contentItem.Password, Membership.Provider);
+ if (passwordChangeResult.Success)
{
- if (Membership.Provider.EnablePasswordReset == false)
- {
- ModelState.AddPropertyError(
- new ValidationResult("Password reset is not enabled", new[] { "resetPassword" }),
- string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
- }
- else if (Membership.Provider.RequiresQuestionAndAnswer && contentItem.Password.Answer.IsNullOrWhiteSpace())
- {
- ModelState.AddPropertyError(
- new ValidationResult("Password reset requires a password answer", new[] {"resetPassword"}),
- string.Format("{0}password", Constants.PropertyEditors.InternalGenericPropertiesPrefix));
- }
- else
- {
- //ok, we should be able to reset it
- try
- {
- var newPass = Membership.Provider.ResetPassword(
- membershipUser.UserName,
- Membership.Provider.RequiresQuestionAndAnswer ? contentItem.Password.Answer : null);
-
- //return the generated pword
- return newPass;
- }
- catch (Exception ex)
- {
- LogHelper.WarnWithException