import java.util.List;
import java.util.Locale;
import java.util.Set;
+import java.util.TreeSet;
+import club.wpia.gigi.Gigi;
import club.wpia.gigi.GigiApiException;
import club.wpia.gigi.database.GigiPreparedStatement;
import club.wpia.gigi.database.GigiResultSet;
-import club.wpia.gigi.dbObjects.Assurance.AssuranceType;
import club.wpia.gigi.dbObjects.CATS.CATSType;
import club.wpia.gigi.dbObjects.Country.CountryCodeType;
+import club.wpia.gigi.dbObjects.Verification.VerificationType;
+import club.wpia.gigi.email.EmailProvider;
import club.wpia.gigi.localisation.Language;
import club.wpia.gigi.output.DateSelector;
import club.wpia.gigi.pages.PasswordResetPage;
import club.wpia.gigi.util.DayDate;
import club.wpia.gigi.util.Notary;
import club.wpia.gigi.util.PasswordHash;
-import club.wpia.gigi.util.PasswordStrengthChecker;
import club.wpia.gigi.util.TimeConditions;
/**
- * Represents an acting, assurable, user. Synchronizing on user means: no
- * name-change and no assurance.
+ * Represents an acting, verifiable user. Synchronizing on user means: no
+ * name-change and no verification.
*/
public class User extends CertificateOwner {
private String email;
- private Assurance[] receivedAssurances;
+ private Verification[] receivedVerifications;
- private Assurance[] madeAssurances;
+ private Verification[] madeVerifications;
private Locale locale;
}
public User(String email, String password, DayDate dob, Locale locale, Country residenceCountry, NamePart... preferred) throws GigiApiException {
+ super(validate(email));
+
this.email = email;
this.dob = dob;
this.locale = locale;
query.setString(7, residenceCountry == null ? null : residenceCountry.getCode());
query.execute();
}
+
new EmailAddress(this, email, locale);
}
+ private static Void validate(String email) {
+ // Avoid storing information that obviously won't get through
+ if ( !EmailProvider.isValidMailAddress(email)) {
+ throw new IllegalArgumentException("Invalid email.");
+ }
+ return null;
+ }
+
public Name[] getNames() {
try (GigiPreparedStatement gps = new GigiPreparedStatement("SELECT `id` FROM `names` WHERE `uid`=? AND `deleted` IS NULL", true)) {
gps.setInt(1, getId());
public void setDoB(DayDate dob) throws GigiApiException {
synchronized (Notary.class) {
- if (getReceivedAssurances().length != 0) {
+ if (getReceivedVerifications().length != 0) {
throw new GigiApiException("No change after verification allowed.");
}
throw new GigiApiException("Entered date of birth is below the restricted age requirements.");
}
- if (CalendarUtil.isOfAge(dob, User.MAXIMUM_PLAUSIBLE_AGE)) {
+ if (CalendarUtil.isYearsInFuture(dob.end(), User.MAXIMUM_PLAUSIBLE_AGE)) {
throw new GigiApiException("Entered date of birth exceeds the maximum age set in our policies. Please check your DoB is correct and contact support if the issue persists.");
}
this.dob = dob;
}
private void setPassword(String newPass) throws GigiApiException {
- PasswordStrengthChecker.assertStrongPassword(newPass, getNames(), getEmail());
+ Name[] names = getNames();
+ TreeSet<String> nameParts = new TreeSet<>();
+ for (int i = 0; i < names.length; i++) {
+ for (NamePart string : names[i].getParts()) {
+ nameParts.add(string.getValue());
+ }
+ }
+ GigiApiException gaPassword = Gigi.getPasswordChecker().checkPassword(newPass, nameParts.toArray(new String[nameParts.size()]), getEmail());
+ if (gaPassword != null) {
+ throw gaPassword;
+ }
try (GigiPreparedStatement ps = new GigiPreparedStatement("UPDATE users SET `password`=? WHERE id=?")) {
ps.setString(1, PasswordHash.hash(newPass));
ps.setInt(2, getId());
}
}
- public boolean canAssure() {
+ public boolean canVerify() {
if (POJAM_ENABLED) {
if ( !CalendarUtil.isOfAge(dob, POJAM_AGE)) { // PoJAM
return false;
return false;
}
}
- if (getAssurancePoints() < 100) {
+ if (getVerificationPoints() < 100) {
return false;
}
public boolean hasPassedCATS() {
try (GigiPreparedStatement query = new GigiPreparedStatement("SELECT 1 FROM `cats_passed` where `user_id`=? AND `variant_id`=?")) {
query.setInt(1, getId());
- query.setInt(2, CATSType.ASSURER_CHALLENGE.getId());
+ query.setInt(2, CATSType.AGENT_CHALLENGE.getId());
try (GigiResultSet rs = query.executeQuery()) {
if (rs.next()) {
return true;
}
}
- public int getAssurancePoints() {
+ public int getVerificationPoints() {
try (GigiPreparedStatement query = new GigiPreparedStatement("SELECT SUM(lastpoints) FROM ( SELECT DISTINCT ON (`from`, `method`) `from`, `points` as lastpoints FROM `notary` INNER JOIN `names` ON `names`.`id`=`to` WHERE `notary`.`deleted` is NULL AND (`expire` IS NULL OR `expire` > CURRENT_TIMESTAMP) AND `names`.`uid` = ? ORDER BY `from`, `method`, `when` DESC) as p")) {
query.setInt(1, getId());
public int getExperiencePoints() {
try (GigiPreparedStatement query = new GigiPreparedStatement("SELECT count(*) FROM ( SELECT `names`.`uid` FROM `notary` INNER JOIN `names` ON `names`.`id` = `to` WHERE `from`=? AND `notary`.`deleted` IS NULL AND `method` = ? ::`notaryType` GROUP BY `names`.`uid`) as p")) {
query.setInt(1, getId());
- query.setEnum(2, AssuranceType.FACE_TO_FACE);
+ query.setEnum(2, VerificationType.FACE_TO_FACE);
GigiResultSet rs = query.executeQuery();
int points = 0;
}
/**
- * Gets the maximum allowed points NOW. Note that an assurance needs to
+ * Gets the maximum allowed points NOW. Note that a verification needs to
* re-check PoJam as it has taken place in the past.
*
* @return the maximal points @
*/
@SuppressWarnings("unused")
- public int getMaxAssurePoints() {
+ public int getMaxVerifyPoints() {
if ( !CalendarUtil.isOfAge(dob, ADULT_AGE) && POJAM_ENABLED) {
return 10; // PoJAM
}
public boolean isValidName(String name) {
for (Name n : getNames()) {
- if (n.matches(name) && n.getAssurancePoints() >= 50) {
+ if (n.matches(name) && n.getVerificationPoints() >= 50) {
return true;
}
}
throw new GigiApiException("Email not one of user's email addresses.");
}
- public synchronized Assurance[] getReceivedAssurances() {
- if (receivedAssurances == null) {
+ public synchronized Verification[] getReceivedVerifications() {
+ if (receivedVerifications == null) {
try (GigiPreparedStatement query = new GigiPreparedStatement("SELECT * FROM `notary` INNER JOIN `names` ON `names`.`id` = `notary`.`to` WHERE `names`.`uid`=? AND `notary`.`deleted` IS NULL ORDER BY `when` DESC")) {
query.setInt(1, getId());
GigiResultSet res = query.executeQuery();
- List<Assurance> assurances = new LinkedList<Assurance>();
+ List<Verification> verifications = new LinkedList<Verification>();
while (res.next()) {
- assurances.add(assuranceByRes(res));
+ verifications.add(verificationByRes(res));
}
- this.receivedAssurances = assurances.toArray(new Assurance[0]);
+ this.receivedVerifications = verifications.toArray(new Verification[0]);
}
}
- return receivedAssurances;
+ return receivedVerifications;
}
- public synchronized Assurance[] getMadeAssurances() {
- if (madeAssurances == null) {
+ public synchronized Verification[] getMadeVerifications() {
+ if (madeVerifications == null) {
try (GigiPreparedStatement query = new GigiPreparedStatement("SELECT * FROM notary WHERE `from`=? AND deleted is NULL ORDER BY `when` DESC")) {
query.setInt(1, getId());
try (GigiResultSet res = query.executeQuery()) {
- List<Assurance> assurances = new LinkedList<Assurance>();
+ List<Verification> verifications = new LinkedList<Verification>();
while (res.next()) {
- assurances.add(assuranceByRes(res));
+ verifications.add(verificationByRes(res));
}
- this.madeAssurances = assurances.toArray(new Assurance[0]);
+ this.madeVerifications = verifications.toArray(new Verification[0]);
}
}
}
- return madeAssurances;
+ return madeVerifications;
}
- public synchronized void invalidateMadeAssurances() {
- madeAssurances = null;
+ public synchronized void invalidateMadeVerifications() {
+ madeVerifications = null;
}
- public synchronized void invalidateReceivedAssurances() {
- receivedAssurances = null;
+ public synchronized void invalidateReceivedVerifications() {
+ receivedVerifications = null;
}
private void rawUpdateUserData() {
}
+ public synchronized String getInitials() {
+ return preferredName.toInitialsString();
+ }
+
public boolean isInGroup(Group g) {
return groups.contains(g);
}
}
public static User getResetWithToken(int id, String token) {
- try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `memid` FROM `passwordResetTickets` WHERE `id`=? AND `token`=? AND `used` IS NULL AND `created` > CURRENT_TIMESTAMP - interval '1 hours' * ?")) {
+ try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT `memid` FROM `passwordResetTickets` WHERE `id`=? AND `token`=? AND `used` IS NULL AND `created` > CURRENT_TIMESTAMP - interval '1 hours' * ?::INTEGER")) {
ps.setInt(1, id);
ps.setString(2, token);
ps.setInt(3, PasswordResetPage.HOUR_MAX);
}
}
- private Assurance assuranceByRes(GigiResultSet res) {
+ private Verification verificationByRes(GigiResultSet res) {
try {
- return new Assurance(res.getInt("id"), User.getById(res.getInt("from")), Name.getById(res.getInt("to")), res.getString("location"), res.getString("method"), res.getInt("points"), res.getString("date"), res.getString("country") == null ? null : Country.getCountryByCode(res.getString("country"), CountryCodeType.CODE_2_CHARS), res.getTimestamp("expire"));
+ return new Verification(res.getInt("id"), User.getById(res.getInt("from")), Name.getById(res.getInt("to")), res.getString("location"), res.getString("method"), res.getInt("points"), res.getString("date"), res.getString("country") == null ? null : Country.getCountryByCode(res.getString("country"), CountryCodeType.CODE_2_CHARS), res.getTimestamp("expire"));
} catch (GigiApiException e) {
throw new Error(e);
}
}
public boolean isInVerificationLimit() {
- try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT 1 FROM `notary` INNER JOIN `names` ON `names`.`id`=`to` WHERE `names`.`uid` = ? AND `when` > (now() - (interval '1 month' * ?)) AND (`expire` IS NULL OR `expire` > now()) AND `notary`.`deleted` IS NULL;")) {
+ try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT 1 FROM `notary` INNER JOIN `names` ON `names`.`id`=`to` WHERE `names`.`uid` = ? AND `when` > (now() - (interval '1 month' * ?::INTEGER)) AND (`expire` IS NULL OR `expire` > now()) AND `notary`.`deleted` IS NULL;")) {
ps.setInt(1, getId());
ps.setInt(2, VERIFICATION_MONTHS);