Jason Jason - 6 months ago 64
AngularJS Question

Angular password generator service

I have a password generator and I was using it in two different controllers so I thought I should move it into a service.


  1. I am not 100% sure a service is the best approach and would like to know what is if it is not.

  2. I am running into one problem. The service sends back a passWord object when I update the password input field I have to use
    ng-model="passWord.password"
    .



Here is the problem:

Because the form has other fields that use
user.VALUE
I need to have my password field read
ng-model="user.password"
but this is breaking in the service. Below is the code.

Service:

app.factory('PassWord', function($resource, $log, $rootScope, $location, $sessionStorage, $q, Data){

var passWord = {
inputType:"password",
showPwTxt:"Show"
};

// Hide & show password function
passWord.hideShowPassword = function(){
if (passWord.inputType == 'password') {
type = 'text';
txt = 'Hide';
}
else {
type = 'password';
txt = 'Show';
}

passWord.inputType = type;
passWord.showPwTxt = txt;

};

// test for medium and strong passwords
var strongRegex = new RegExp("^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-!@#\"\$%\^&\*()_+|=\\]\\[{}~`:\";\'<>?,.\/])(?=.{8,})");
var mediumRegex = new RegExp("^(((?=.*[a-z])(?=.*[A-Z]))|((?=.*[a-z])(?=.*[0-9]))|((?=.*[A-Z])(?=.*[0-9])))(?=.{6,})");

// create an object for the pw strength
passWord.passwordStrength = {};

passWord.analyze = function(value) {
if(strongRegex.test(value)) {
color = "#57A83F";
txt = "Strong";
} else if(mediumRegex.test(value)) {
color = "#FF9800";
txt = "Medium";
} else {
color = "#E03930";
txt = "Weak";
}

passWord.passwordStrength["color"] = color;
passWord.pwStrengthTxt = txt;

};

// password generator
passwordLength = 12;
addUpper = true;
addNumbers = true;
addSymbols = true;

passWord.createPassword = function(){
var lowerCharacters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];
var upperCharacters = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
var numbers = ['0','1','2','3','4','5','6','7','8','9'];
var symbols = ['!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', ']', '^', '_', '`', '{', '|', '}', '~'];
var finalCharacters = lowerCharacters;
//if(passWord.addUpper){
finalCharacters = finalCharacters.concat(upperCharacters);
//}
//if(passWord.addNumbers){
finalCharacters = finalCharacters.concat(numbers);
//}
//if(passWord.addSymbols){
finalCharacters = finalCharacters.concat(symbols);
//}
var passwordArray = [];
for (var i = 1; i < passwordLength; i++) {
passwordArray.push(finalCharacters[Math.floor(Math.random() * finalCharacters.length)]);
};

//update the passwrod input field in the form
passWord.password = passwordArray.join("");

//analyze thepassword strength
passWord.analyze(passWord.password);

if(passWord.pwStrengthTxt == "Medium" || passWord.pwStrengthTxt == "Weak") {
passwordArray = [];
passWord.createPassword();
}
};

return passWord;
});


HTML:

<form name="resetForm" class="" role="form">

<div class="form-group row" ng-show="!uid">

<div class="col-sm-12">

<input type="email" class="form-control" placeholder="Email" name="email" ng-model="user.email" ng-required="!uid"/>

<span ng-show="!resetForm.email.$error.required && !resetForm.email.$error.email" class="glyphicon glyphicon-ok form-control-feedback" ></span>

<span ng-show="resetForm.email.$touched">
<small class="errorMessage" data-ng-show="resetForm.email.$error.required">Email is required.</small>
</span>

<small class="errorMessage" ng-show="resetForm.email.$error.email">Email is not valid</small>

</div>

</div>

<div class="form-group row" ng-hide="!uid">
<div class="col-sm-12">
<span class="block input-icon input-icon-right">
<div class="input-group">
<input type="{{passWord.inputType}}" class="form-control" name="password" placeholder="Password" ng-minlength="6" ng-model="passWord.password" ng-change="passWord.analyze(passWord.password)" ng-required="uid"/>
<span id="spnPassword" class="add-on input-group-addon" ng-click="passWord.hideShowPassword()" style="cursor:pointer;">{{passWord.showPwTxt}}</span>
</div>
<span ng-hide="resetForm.password.$error.required || resetForm.password.$error.minlength" class="glyphicon glyphicon-ok form-control-feedback" ></span>
<small class="errorMessage" ng-show="resetForm.password.$error.minlength">Too short! Minimum 6 characers</small>
</span>
<div ng-show="passWord.password.length">
<small>Password strength: <span ng-style="passWord.passwordStrength">{{passWord.pwStrengthTxt}}</span></small>
</div>
<br>
<button type="button" class="btn btn-sm btn-primary" data-ng-click="passWord.createPassword()">Generate Password</button>
</div>
</div>

<div class="clearfix">
<div class="row">

<span class="lbl col-sm-7"><span ng-show="!uid">Remembered your password? <a href="login">SignIn</a></span></span>

<div class="col-sm-5 text-right">
<button type="submit" class="btn btn-info" ng-click="resetPassword(user)" data-ng-disabled="resetForm.$invalid">Reset Password</button>
</div>

</div>
</div>

</form>


CONTROLLER:

app.controller('resetCtrl', function ($scope, $rootScope, $log, $routeParams, $location, $http, Data, PassWord) {

$scope.user = {email:'',password:''};

$scope.passWord = PassWord;

$scope.resetPassword = function (user) {
$log.log('user is - ',user);
// Do Stuff
};

});

Answer

Services seem like a good way to handle this. Just adjust your code slightly to support the password field on the user object. then abstract the service method in the controller so you can update your scope.

app.controller('resetCtrl', function ($scope, $rootScope, $log, $routeParams, $location, $http, Data, PassWord) {

    $scope.user = {email:'',password:''};

    $scope.user.password = PassWord.createPassword();

    $scope.generateNewPassword = function() {
        $scope.user.password = PassWord.createPassword();
    }
});

Then update template with new generate password function

<button type="button" class="btn btn-sm btn-primary" data-ng-click="generateNewPassword()">Generate Password</button>

Also update the password model in your input box to match the user object ng-model="passWord.password" to ng-model="user.password"

Comments