How to specify which condition is not matching? - javascript

I have a regex pattern that I'd like to apply to passwords:
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[[:punct:]])./
There are 4 capture groups. I'd like to be able to know which of the capture groups don't match the supplied string, so I can give specific feedback to a user.
For example:
abcd43 -> 1st & 3rd groups true; 2nd and 4th false
(So I can customize an error: "Your password must contain at least one capital letter and a punctuation character.")

The simplest way is to check the four groups separately.
You can use something as easy as:
if(!lowerCase(pass))
print "No lower case letters"
else if(!upperCase(pass))
print "No upper"
else if(!digits(pass))
print "No digits"
etc...

Just set a varibale as your match group and check for every group:
var pattern =/...../ //whatever
var ma = 'my string'.match(pattern);
if (!ma)
console.log('No match');
else{
console.log(ma[0]) // first group.
console.log(m[1]); // second group;
}
Now simply check that each group has a value or not and each index represents the corresponding parenthesis in-order:
if (!m[0]){
alert('your password does not match first parenthesis');
}

Javascript does not directly support named capture groups in regular expressions. Your best bet then would be to simply check the groups, and map the numbers to a condition, perhaps through an array. So you might have 1 -> "lower case", 2 -> "upper case", etc.
Then just build a message corresponding to the failure(s), and display that message.
"lower case" -> "Passwords must contain at least one lower case letter"
"upper case" -> "Passwords must contain at least one upper case letter."
Now, with that said, PLEASE, PLEASE don't do this. I use a password generator, plus a password store, for my logins. If you're going to impose more restrictions than just length, please publish them all, right up front. Don't try to "customize" the error message to tell me what I'm missing. (And, realistically, just require a long password. If you require 16 characters with no other limits, you're more secure than 8 characters with 1 digit, 1 cap, and 1 punct.)

Related

Looking for ways to validate a username

I'm trying to validate usernames when using a tag function against these criteria:
Only contains alphanumeric characters, underscore and dot.
Dot can't be at the end or start of a username (e.g .username / username.).
Dot and underscore can't be next to each other (e.g user_.name).
Dot can't be used multiple times in a row (e.g. user..name).
The username ends when there is a character other than the allowed characters (e.g. #user#next or #user/nnnn would only validate user as a valid username)
Another username can only be written after a space. (e.g. #user #next would validate two usernames while #user#next would only validate user)
I have tried this so far:
^(?=.{8,20}$)(?![.])(?!.*[.]{2})[a-zA-Z0-9.]+(?<![.])$ and have dealt the multiple usernames problem with for loops.
I was wondering what would be the best way to implement something like this (e.g. regex, for loops, combination). I tried using regex but realised it is very specific and can get complicated.
Use the following regex:
(?!\.)(?![a-zA-Z._]*(?:\._|_\.|\.\.))[a-zA-Z._]*[a-zA-Z_]
(?!\.): Negative lookahead assertion to ensure the name cannot begin with a '.'
(?![a-zA-Z._]*(?:\._|_\.|\.\.)): Negative lookahead assertion that the name does not contain ._ nor _. nor .. in succession.
[a-zA-Z._]*[a-zA-Z_]: Ensures the name is at least one-character long and does not end with ..
See Regex Demo
However, the results are not necessarily what you might expect since you want to stop scanning a name when you come to the first character that is not part of a valid name but you continue scanning looking for more valid names. So when the input is, for example, .user, you stop scanning when you see the . because you know that a name cannot begin with .. But you then resume scanning and still end up scanning user as a valid name.
let text = 'user user_xyx_abc user__def user_.abc user._abc user..abc user_abc. .user';
let regexp = /(?!\.)(?![a-zA-Z._]*(?:\._|_\.|\.\.))[a-zA-Z._]*[a-zA-Z_]/g;
let matches = text.matchAll(regexp);
for (let match of matches) {
console.log(match);
}
Ideally, your input would contain only a single user name that you are validating and the entire input should match your regex. Then, you would use anchors in your regex:
^(?!\.)(?![a-zA-Z._]*(?:\._|_\.|\.\.))[a-zA-Z._]*[a-zA-Z_]$
See Regex Demo
But given your current circumstances, you might consider splitting your input on whitespace, trimming extra whitespace from the beginning and end of the strings, and then use the above regex on each individual user name:
let text = 'user user_xyx_abc user__def user_.abc user._abc user..abc user_abc. .user ';
let names = text.split(/\s+/);
let regexp = /^(?!\.)(?![a-zA-Z._]*(?:\._|_\.|\.\.))[a-zA-Z._]*[a-zA-Z_]$/;
for (name of names) {
if (regexp.test(name))
console.log(name);
}

Regex- match 3 or 6 of type

I'm writing an application that requires color manipulation, and I want to know when the user has entered a valid hex value. This includes both '#ffffff' and '#fff', but not the ones in between, like 4 or 5 Fs. My question is, can I write a regex that determines if a character is present a set amount of times or another exact amount of times?
What I tried was mutating the:
/#(\d|\w){3}{6}/
Regular expression to this:
/#(\d|\w){3|6}/
Obviously this didn't work. I realize I could write:
/(#(\d|\w){3})|(#(\d|\w){6})/
However I'm hoping for something that looks better.
The shortest I could come up with:
/#([\da-f]{3}){1,2}/i
I.e. # followed by one or two groups of three hexadecimal digits.
You can use this regex:
/#[a-f\d]{3}(?:[a-f\d]{3})?\b/i
This will allow #<3 hex-digits> or #<6 hex-digits> inputs. \b in the end is for word boundary.
RegEx Demo
I had to find a pattern for this myself today but I also needed to include the extra flag for transparency (i.e. #FFF5 / #FFFFFF55). Which made things a little more complicated as the valid combinations goes up a little.
In case it's of any use, here's what I came up with:
var inputs = [
"#12", // Invalid
"#123", // Valid
"#1234", // Valid
"#12345", // Invalid
"#123456", // Valid
"#1234567", // Invalid
"#12345678", // Valid
"#123456789" // Invalid
];
var regex = /(^\#(([\da-f]){3}){1,2}$)|(^\#(([\da-f]){4}){1,2}$)/i;
inputs.forEach((itm, ind, arr) => console.log(itm, (regex.test(itm) ? "valid" : "-")));
Which should return:
#123 valid
#1234 valid
#12345 -
#123456 valid
#1234567 -
#12345678 valid
#123456789 -

Regex for password must be 6 to 8 characters long containing at least 3 alphabets, 2 number, no special character, Must not contain the sequence ‘pas’

I am trying to write a regular expression to validate a password which must meet the following criteria:
a. Password must be 6 to 8 characters long, contain at least 3 alpha and 2 numeric characters and no special characters.
b. Must not contain the sequence ‘pas’.
What I've tried so far:
/^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])([a-zA-Z0-9]{8})$/
I suggest you to not use only one regex, because that way the users would not know why their password are failing.
I would do something like this:
function checkPassword (pass) {
pass = {
text: pass,
length: pass.length,
letters: pass.match(/[a-z]/gi).length,
digits: pass.match(/[0-9]/g).length,
contains_pas: !!pass.match(/pas/i) // <- will result true/false
}
pass.specials = pass.length - pass.letters - pass.digits;
// here you can use your logic
// example:
if (pass.contains_pas) {
alert('The password can not contains "pas".');
}
return pass; // you can return or not
}
Hope it helps.
You can try this:
([[a-zA-Z]{3,}+[0-9]{2}])^((?!pas).)$
It works only if user enters consecutive alphabets and then numbers. So, its a partial solution to this problem.
For the stated problem, I would suggest not to use reg-ex. As, reg-ex validates a particular order, you should incorporate separate checks for each test.

Regex to validate 3 specific forms of a phone number

So I am trying to write code that will evaluate if a phone number is valid in one of three ways.
The first is the form xxx-xxx-xxxx, the second is (xxx) xxx-xxxx, and the third is xxxxxxxxxx.
Here's my regular expression:
if (/^\d{3}-\d{3}-\d{4}$/.test(phoneVal) || /^\d{10}$/.test(phoneVal) || /^\(\d{3}\) \d{3}-\d{4}$/.test(phoneVal)) {
return true;
}
However whenever I put in what I would consider to be a valid phone number, it trips up this regular expression, and gives the error:
else {
alert("Please put in a correct phone number");
return false;
}
When running this: phoneVal = document.getElementById("phone");
alert(phoneVal); I get: [Object HTML InputElement]
You're getting the element rather than its value. Use the value property:
phoneVal = document.getElementById("phone").value;
Here's a tested function which meets your requirements:
// Validate 10 digit US phone number in one of three specific formats.
function validatePhoneNumber(text) {
/* # Validate US phone number in one of three specific formats.
^ # Anchor to start of string.
(?: # Group alternatives.
[0-9]{3}-[0-9]{3}-[0-9]{4} # Either xxx-xxx-xxxx
| \([0-9]{3}\)[ ][0-9]{3}-[0-9]{4} # or (xxx) xxx-xxxx
| [0-9]{10} # or xxxxxxxxxx
) # End group of alternatives.
$ # Anchor to end of string.
*/
var re = /^(?:[0-9]{3}-[0-9]{3}-[0-9]{4}|\([0-9]{3}\)[ ][0-9]{3}-[0-9]{4}|[0-9]{10})$/;
return re.test(text);
}
That said, as others have pointed out, you should allow users to input a more loosely defined number. See my answer to your other (nearly identical) question which is more forgiving.
I think when it comes to phone numbers you need to give you're users freedom to write the number in one of their own prefered format.
The regex below matches ##########, ###.###.####, ###-###-####, ### ### ####, (###) ### ####, (###)-###-#### and many more combinations.
if(/\(?\b[0-9]{3}\)?[-. ]?[0-9]{3}[-. ]?[0-9]{4}\b/.test(phoneVal))
{
return true;
} else
return false;
}
For phone numbers, I tend to strip out any characters that's not A-Z, 0-9, and then make sure the result is numeric, and 10 digits long. Some people use periods, dashes, brackets, spaces, etc. 1-23--4..5#678_9%0 would be a valid phone number, but when I store it in the database, I normalize it to 1234567890, and then when presenting it back, I format it myself in the format of my own choosing, such as 123-456-7890.

Email address check in Javascript

I think many people have done some similar development tasks before:
I would like to check the people's email address whether only match #tomtom.com or #stream.com.
Currently, I have two solutions in my mind:
Using indexof() function
var checkTomTomEmail=eo.data.username.indexOf("#tomtom.com");
var checkStreamEmail=eo.data.username.indexOf("#stream.com");
if (checkTomTomEmail >0 || checkStreamEmail >0 )
{
//Run the login code
}
Else
{
//Please login with your tomtom or stream email
}
Using match
var patt1=/#tomtom.com/gi;
var patt2=/#stream.com/gi;
var checkTomTomEmail=eo.data.username.match(patt1);
var checkStreamEmail=eo.data.username.match(patt2);
if(indexOf(checkTomTomEmail)> 1 ||indexOf (checkStreamEmail)>1)
{
//Login
}
I still think I do not consider all the detail yet. Any suggestions?
Thanks
Perhaps if people are only allowed to enter emails for those two addresses you should only collect the username and then allow them to choose #tomtom.com or #stream.com using radiobuttons.
If you still want to go the javascript route then your regex can be combined into a single statement
var emailPatt=/#(tomtom|stream).com/gi;
if(emailPatt.test(eo.data.username))
{
//Login
}
How about this...
var emailRegex = /^([0-9a-z])+#(tomtom|stream)\.com$/ig;
if (emailRegex.test(emailRegex)) {
// Login
}
Instead of performing a .match(...) - Which you'll get a string back, we can perform a .test(...) to see if anything matches.
This pattern guarantees the following:
The "username" part of the email address must at least have a SINGLE character (For example, a#stream.com)
Username must be composed of a digit or an alphabet (Upper/Lower case - Doesn't matter because of the /i at the end)
Input must contain the entire email address without leading or tailing spaces. For example, " user#tomtom.com " will fail, it'll only accept "user#tomtom.com".)
You can customize this further by, saying, making sure username must have at least 3 characters, you can use underscore or dashes in the email address, etc.
To answer your question, both solutions won't work. Reasons:
User can enter "tom#tomtom.com Hello", and it'll pass both of your validation.
Specifically on solution #2, the dot '.' is a Regex-reserved character, it means it'll match anything, so, if the user enters " #tomtom1com", it'll pass...
More on Regex: http://www.regular-expressions.info/reference.html

Categories