]> WPIA git - gigi.git/blob - src/club/wpia/gigi/passwords/PasswordStrengthChecker.java
Merge changes from topic '143'
[gigi.git] / src / club / wpia / gigi / passwords / PasswordStrengthChecker.java
1 package club.wpia.gigi.passwords;
2
3 import java.util.Arrays;
4 import java.util.TreeSet;
5 import java.util.regex.Pattern;
6
7 import club.wpia.gigi.GigiApiException;
8 import club.wpia.gigi.dbObjects.Name;
9 import club.wpia.gigi.dbObjects.NamePart;
10 import club.wpia.gigi.output.template.SprintfCommand;
11
12 public class PasswordStrengthChecker implements PasswordChecker {
13
14     private static Pattern digits = Pattern.compile("\\d");
15
16     private static Pattern lower = Pattern.compile("[a-z]");
17
18     private static Pattern upper = Pattern.compile("[A-Z]");
19
20     private static Pattern whitespace = Pattern.compile("\\s");
21
22     private static Pattern special = Pattern.compile("(?!\\s)\\W");
23
24     public PasswordStrengthChecker() {}
25
26     /**
27      * @param pw The password.
28      * @return Estimate of the password’s strength (positive).
29      */
30     private int ratePasswordStrength(String pw) {
31         int points = 0;
32         if (pw.length() > 15) {
33             points++;
34         }
35         if (pw.length() > 20) {
36             points++;
37         }
38         if (pw.length() > 25) {
39             points++;
40         }
41         if (pw.length() > 30) {
42             points++;
43         }
44         if (digits.matcher(pw).find()) {
45             points++;
46         }
47         if (lower.matcher(pw).find()) {
48             points++;
49         }
50         if (upper.matcher(pw).find()) {
51             points++;
52         }
53         if (special.matcher(pw).find()) {
54             points++;
55         }
56         if (whitespace.matcher(pw).find()) {
57             points++;
58         }
59         return points;
60     }
61
62     /**
63      * @param pw The password.
64      * @param nameParts The name parts of the user.
65      * @param email The email address of the user.
66      * @return Estimate of the password’s weakness (negative).
67      */
68     private int ratePasswordWeakness(String pw, String[] nameParts, String email) {
69         int points = 0;
70         if (contained(pw, email)) {
71             points -= 2;
72         }
73         for (int i = 0; i < nameParts.length; i++) {
74             if (contained(pw, nameParts[i])) {
75                 points -= 2;
76             }
77         }
78         return points;
79     }
80
81     public int ratePassword(String pw, String[] nameParts, String email) {
82         return ratePasswordStrength(pw) + ratePasswordWeakness(pw, nameParts, email);
83     }
84
85     @Override
86     public GigiApiException checkPassword(String password, String[] nameParts, String email) {
87         int points = ratePassword(password, nameParts, email);
88         if (points < 3) {
89             return new GigiApiException(new SprintfCommand(
90                 "The Password you submitted failed to contain enough differing characters and/or contained words from your name and/or email address. For the current requirements and to learn more, visit our {0}FAQ{1}.",
91                 Arrays.asList("!(/kb/goodPassword", "!'</a>'")
92             ));
93         } else {
94             return null;
95         }
96     }
97
98     private static boolean contained(String pw, String check) {
99         if (check == null || check.equals("")) {
100             return false;
101         }
102         if (pw.contains(check)) {
103             return true;
104         }
105         if (check.contains(pw)) {
106             return true;
107         }
108         return false;
109     }
110
111 }