Skip to content

Commit 9fd1e1a

Browse files
authored
Merge pull request #3 from arghyadeep-k/dev
Dev
2 parents 4344b29 + 4e79241 commit 9fd1e1a

File tree

4 files changed

+167
-103
lines changed

4 files changed

+167
-103
lines changed

.github/workflows/deno-ci.yml

+7-5
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88

99
name: CI
1010

11-
on:
12-
push:
13-
branches: [main]
14-
pull_request:
15-
branches: [main]
11+
on: [push, pull_request]
12+
# push:
13+
# branches:
14+
# - dev
15+
# - main
16+
# pull_request:
17+
# branches: [main]
1618

1719
jobs:
1820
test:

README.md

+24-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ Deno🦕 module to test if a password/string fulfills all the preset criterias.
1818
import { checkPassword } from "https://deno.land/x/password_checker/mod.ts";
1919
```
2020

21+
or
22+
23+
```typescript
24+
import { checkPasswordWithResult } from "https://deno.land/x/password_checker/mod.ts";
25+
```
26+
2127
## Parameters
2228

2329
### Mandatory Parameters:
@@ -42,7 +48,13 @@ import { checkPassword } from "https://deno.land/x/password_checker/mod.ts";
4248

4349
## Output
4450

45-
Returns true if password passes all checks.
51+
- If `checkPassword()` is invoked:
52+
- Returns `true` if password passes all the checks, else `false`.
53+
- If `checkPasswordWithResult()` is invoked:
54+
- `isValid: boolean` - `true` if the password is valid and passes all the
55+
checks, else `false`.
56+
- `reason: string` - The reason why the input password was marked as invalid.
57+
Returns undefined in case `isValid` is `true`.`
4658

4759
## Usage
4860

@@ -93,6 +105,17 @@ isPasswordValid = checkPassword({
93105
});
94106
```
95107

108+
If you want the reason of failure as well, you can use
109+
`checkPasswordWithResult()` which returns an object of type
110+
`VerificationResult`.
111+
112+
```typescript
113+
interface VerificationResult {
114+
isValid: boolean;
115+
reason?: string;
116+
}
117+
```
118+
96119
## Reference
97120

98121
- https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10k-most-common.txt

mod.ts

+46-28
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
interface IParams {
1+
export interface IParams {
22
password: string;
33
minLen?: number;
44
maxLen?: number;
@@ -8,6 +8,11 @@ interface IParams {
88
checkWithCommonPasswords?: boolean;
99
}
1010

11+
export interface VerificationResult {
12+
isValid: boolean;
13+
reason?: string;
14+
}
15+
1116
const url =
1217
"https://raw.githubusercontent.com/danielmiessler/SecLists/master/Passwords/Common-Credentials/10k-most-common.txt";
1318
const response = await fetch(
@@ -16,46 +21,59 @@ const response = await fetch(
1621

1722
const passwordList = await response.text();
1823

19-
export function checkPassword({
24+
export function checkPasswordWithResult({
2025
password,
2126
minLen = 0,
2227
maxLen = 0,
2328
containsNum = true,
2429
containsSpecialChar = true,
2530
containsAlphabet = true,
2631
checkWithCommonPasswords = false,
27-
}: IParams): boolean {
28-
if (minLen != 0) {
29-
if (password.length < minLen) {
30-
return false;
31-
}
32+
}: IParams): VerificationResult {
33+
if (minLen != 0 && password.length < minLen) {
34+
return {
35+
isValid: false,
36+
reason: `The password should contain at least ${minLen} characters`,
37+
};
3238
}
33-
if (maxLen != 0) {
34-
if (password.length > maxLen) {
35-
return false;
36-
}
39+
if (maxLen != 0 && password.length > maxLen) {
40+
return {
41+
isValid: false,
42+
reason: `The password should contain at most ${maxLen} characters`,
43+
};
3744
}
38-
if (containsNum) {
39-
if (password.search(/\d/) == -1) {
40-
return false;
41-
}
45+
if (containsNum && password.search(/\d/) == -1) {
46+
return {
47+
isValid: false,
48+
reason: "The password should contain at least one digit",
49+
};
4250
}
43-
if (containsSpecialChar) {
44-
if (password.search(/[^\w\s]/) == -1) {
45-
return false;
46-
}
51+
if (containsSpecialChar && password.search(/[^\w\s]/) == -1) {
52+
return {
53+
isValid: false,
54+
reason: "The password should contain at least one special character",
55+
};
4756
}
48-
if (containsAlphabet) {
49-
if (password.search(/[A-Za-z]/) == -1) {
50-
return false;
51-
}
57+
if (containsAlphabet && password.search(/[A-Za-z]/) == -1) {
58+
return {
59+
isValid: false,
60+
reason: "The password should contain at least one letter",
61+
};
5262
}
5363

54-
if (checkWithCommonPasswords) {
55-
if (passwordList != undefined && passwordList.includes(password)) {
56-
return false;
57-
}
64+
if (
65+
checkWithCommonPasswords && passwordList != undefined &&
66+
passwordList.includes(password)
67+
) {
68+
return {
69+
isValid: false,
70+
reason: "The password should not be too common",
71+
};
5872
}
5973

60-
return true;
74+
return { isValid: true };
75+
}
76+
77+
export function checkPassword(params: IParams): boolean {
78+
return checkPasswordWithResult(params).isValid;
6179
}

mod_test.ts

+90-69
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,118 @@
11
import { assertEquals } from "./test_deps.ts";
2-
import { checkPassword } from "./mod.ts";
2+
import {
3+
checkPassword,
4+
checkPasswordWithResult,
5+
IParams,
6+
VerificationResult,
7+
} from "./mod.ts";
38

49
Deno.test("Test with defaults", () => {
5-
assertEquals(checkPassword({ password: "random123." }), true);
10+
assertResult({ password: "random123." }, {
11+
isValid: true,
12+
});
613
});
714

815
Deno.test("Test for minimum length", () => {
9-
assertEquals(checkPassword({ password: "random123", minLen: 10 }), false);
16+
assertResult({ password: "random123", minLen: 10 }, {
17+
isValid: false,
18+
reason: "The password should contain at least 10 characters",
19+
});
1020
});
1121

1222
Deno.test("Test for maximum length", () => {
13-
assertEquals(
14-
checkPassword({ password: "random123", minLen: 2, maxLen: 5 }),
15-
false,
16-
);
23+
assertResult({ password: "radnom123", minLen: 2, maxLen: 5 }, {
24+
isValid: false,
25+
reason: "The password should contain at most 5 characters",
26+
});
1727
});
1828

1929
Deno.test("Test for numbers", () => {
20-
assertEquals(
21-
checkPassword({
22-
password: "random",
23-
minLen: 2,
24-
maxLen: 10,
25-
containsNum: true,
26-
}),
27-
false,
28-
);
30+
assertResult({
31+
password: "random",
32+
minLen: 2,
33+
maxLen: 10,
34+
containsNum: true,
35+
}, {
36+
isValid: false,
37+
reason: "The password should contain at least one digit",
38+
});
2939
});
3040

3141
Deno.test("Test for special characters", () => {
32-
assertEquals(
33-
checkPassword({
34-
password: "random123",
35-
minLen: 2,
36-
maxLen: 10,
37-
containsNum: true,
38-
containsSpecialChar: true,
39-
}),
40-
false,
41-
);
42+
assertResult({
43+
password: "random123",
44+
minLen: 2,
45+
maxLen: 10,
46+
containsNum: true,
47+
containsSpecialChar: true,
48+
}, {
49+
isValid: false,
50+
reason: "The password should contain at least one special character",
51+
});
4252
});
4353

4454
Deno.test("Test for alphabets", () => {
45-
assertEquals(
46-
checkPassword({
47-
password: "123456.!",
48-
minLen: 2,
49-
maxLen: 10,
50-
containsNum: true,
51-
containsSpecialChar: true,
52-
containsAlphabet: true,
53-
}),
54-
false,
55-
);
55+
assertResult({
56+
password: "123456.!",
57+
minLen: 2,
58+
maxLen: 10,
59+
containsNum: true,
60+
containsSpecialChar: true,
61+
containsAlphabet: true,
62+
}, {
63+
isValid: false,
64+
reason: "The password should contain at least one letter",
65+
});
5666
});
5767

5868
Deno.test("Test for all options", () => {
59-
assertEquals(
60-
checkPassword({
61-
password: "abc123456.!",
62-
minLen: 2,
63-
maxLen: 12,
64-
containsNum: true,
65-
containsSpecialChar: true,
66-
containsAlphabet: true,
67-
}),
68-
true,
69-
);
69+
assertResult({
70+
password: "abc123456.!",
71+
minLen: 2,
72+
maxLen: 12,
73+
containsNum: true,
74+
containsSpecialChar: true,
75+
containsAlphabet: true,
76+
}, {
77+
isValid: true,
78+
});
7079
});
7180

7281
Deno.test("Test for common password - Positive", () => {
73-
assertEquals(
74-
checkPassword({
75-
password: "batman123.?",
76-
minLen: 2,
77-
maxLen: 12,
78-
checkWithCommonPasswords: true,
79-
}),
80-
true,
81-
);
82+
assertResult({
83+
password: "batman123.?",
84+
minLen: 2,
85+
maxLen: 12,
86+
checkWithCommonPasswords: true,
87+
}, {
88+
isValid: true,
89+
});
8290
});
8391

8492
Deno.test("Test for common password - Negative", () => {
85-
assertEquals(
86-
checkPassword({
87-
password: "batman",
88-
minLen: 2,
89-
maxLen: 12,
90-
containsNum: false,
91-
containsSpecialChar: false,
92-
containsAlphabet: true,
93-
checkWithCommonPasswords: true,
94-
}),
95-
false,
96-
);
93+
assertResult({
94+
password: "batman",
95+
minLen: 2,
96+
maxLen: 12,
97+
containsNum: false,
98+
containsSpecialChar: false,
99+
containsAlphabet: true,
100+
checkWithCommonPasswords: true,
101+
}, {
102+
isValid: false,
103+
reason: "The password should not be too common",
104+
});
97105
});
106+
107+
/**
108+
* Test both `checkPassword` and `checkPasswordWithResult` against the provided case with custom assert function
109+
* @param params
110+
* @param expectedResult
111+
*/
112+
function assertResult(params: IParams, expectedResult: VerificationResult) {
113+
// Invoking checkPassword()
114+
assertEquals(checkPassword(params), expectedResult.isValid);
115+
116+
// Invoking checkPasswordWithResult()
117+
assertEquals(checkPasswordWithResult(params), expectedResult);
118+
}

0 commit comments

Comments
 (0)