]> WPIA git - gigi.git/blob - src/org/cacert/gigi/User.java
fd1989b26aa41e168d4b38cfc54a3eb5270b54ad
[gigi.git] / src / org / cacert / gigi / User.java
1 package org.cacert.gigi;
2
3 import java.sql.Date;
4 import java.sql.PreparedStatement;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.util.Calendar;
8
9 import org.cacert.gigi.database.DatabaseConnection;
10 import org.cacert.gigi.util.PasswordHash;
11 import org.cacert.gigi.util.PasswordStrengthChecker;
12
13 public class User {
14
15     private int id;
16
17     private Name name = new Name(null, null, null, null);
18
19     private Date dob;
20
21     private String email;
22
23     private Assurance[] receivedAssurances, madeAssurances;
24
25     public User(int id) {
26         this.id = id;
27         try {
28             PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `fname`, `lname`,`mname`, `suffix`, `dob`, `email` FROM `users` WHERE id=?");
29             ps.setInt(1, id);
30             ResultSet rs = ps.executeQuery();
31             if (rs.next()) {
32                 name = new Name(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4));
33                 dob = rs.getDate(5);
34                 email = rs.getString(6);
35             }
36             rs.close();
37         } catch (SQLException e) {
38             e.printStackTrace();
39         }
40     }
41
42     public User() {}
43
44     public int getId() {
45         return id;
46     }
47
48     public String getFname() {
49         return name.fname;
50     }
51
52     public String getLname() {
53         return name.lname;
54     }
55
56     public String getMname() {
57         return name.mname;
58     }
59
60     public Name getName() {
61         return name;
62     }
63
64     public void setMname(String mname) {
65         this.name.mname = mname;
66     }
67
68     public String getSuffix() {
69         return name.suffix;
70     }
71
72     public void setSuffix(String suffix) {
73         this.name.suffix = suffix;
74     }
75
76     public Date getDob() {
77         return dob;
78     }
79
80     public void setDob(Date dob) {
81         this.dob = dob;
82     }
83
84     public String getEmail() {
85         return email;
86     }
87
88     public void setEmail(String email) {
89         this.email = email;
90     }
91
92     public void setId(int id) {
93         this.id = id;
94     }
95
96     public void setFname(String fname) {
97         this.name.fname = fname;
98     }
99
100     public void setLname(String lname) {
101         this.name.lname = lname;
102     }
103
104     public void insert(String password) throws SQLException {
105         if (id != 0) {
106             throw new Error("refusing to insert");
107         }
108         PreparedStatement query = DatabaseConnection.getInstance().prepare("insert into `users` set `email`=?, `password`=?, " + "`fname`=?, `mname`=?, `lname`=?, " + "`suffix`=?, `dob`=?, `created`=NOW(), locked=0");
109         query.setString(1, email);
110         query.setString(2, PasswordHash.hash(password));
111         query.setString(3, name.fname);
112         query.setString(4, name.mname);
113         query.setString(5, name.lname);
114         query.setString(6, name.suffix);
115         query.setDate(7, new java.sql.Date(dob.getTime()));
116         query.execute();
117         id = DatabaseConnection.lastInsertId(query);
118     }
119
120     public void changePassword(String oldPass, String newPass) throws GigiApiException {
121         try {
122             PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `password` FROM users WHERE id=?");
123             ps.setInt(1, id);
124             ResultSet rs = ps.executeQuery();
125             if ( !rs.next()) {
126                 throw new GigiApiException("User not found... very bad.");
127             }
128             if ( !PasswordHash.verifyHash(oldPass, rs.getString(1))) {
129                 throw new GigiApiException("Old password does not match.");
130             }
131             rs.close();
132             PasswordStrengthChecker.assertStrongPassword(newPass, this);
133             ps = DatabaseConnection.getInstance().prepare("UPDATE users SET `password`=? WHERE id=?");
134             ps.setString(1, PasswordHash.hash(newPass));
135             ps.setInt(2, id);
136             if (ps.executeUpdate() != 1) {
137                 throw new GigiApiException("Password update failed.");
138             }
139         } catch (SQLException e) {
140             throw new GigiApiException(e);
141         }
142     }
143
144     public boolean canAssure() throws SQLException {
145         if (getAssurancePoints() < 100) {
146             return false;
147         }
148
149         return hasPassedCATS();
150
151     }
152
153     public boolean hasPassedCATS() throws SQLException {
154         PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT 1 FROM `cats_passed` where `user_id`=?");
155         query.setInt(1, id);
156         ResultSet rs = query.executeQuery();
157         if (rs.next()) {
158             return true;
159         } else {
160             return false;
161         }
162     }
163
164     public int getAssurancePoints() throws SQLException {
165         PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT sum(points) FROM `notary` where `to`=? AND `deleted`=0");
166         query.setInt(1, id);
167         ResultSet rs = query.executeQuery();
168         int points = 0;
169         if (rs.next()) {
170             points = rs.getInt(1);
171         }
172         rs.close();
173         return points;
174     }
175
176     public int getExperiencePoints() throws SQLException {
177         PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT count(*) FROM `notary` where `from`=? AND `deleted`=0");
178         query.setInt(1, id);
179         ResultSet rs = query.executeQuery();
180         int points = 0;
181         if (rs.next()) {
182             points = rs.getInt(1) * 2;
183         }
184         rs.close();
185         return points;
186     }
187
188     @Override
189     public boolean equals(Object obj) {
190         if ( !(obj instanceof User)) {
191             return false;
192         }
193         User s = (User) obj;
194         return name.equals(s.name) && email.equals(s.email) && dob.toString().equals(s.dob.toString()); // This
195                                                                                                         // is
196                                                                                                         // due
197                                                                                                         // to
198                                                                                                         // day
199                                                                                                         // cutoff
200     }
201
202     /**
203      * Gets the maximum allowed points NOW. Note that an assurance needs to
204      * re-check PoJam as it has taken place in the past.
205      * 
206      * @return the maximal points
207      * @throws SQLException
208      */
209     public int getMaxAssurePoints() throws SQLException {
210         int exp = getExperiencePoints();
211         int points = 10;
212         Calendar c = Calendar.getInstance();
213         c.setTime(dob);
214         int year = c.get(Calendar.YEAR);
215         int month = c.get(Calendar.MONTH);
216         int day = c.get(Calendar.DAY_OF_MONTH);
217         c.set(year + 18, month, day);
218         if (System.currentTimeMillis() < c.getTime().getTime()) {
219             return points; // not 18 Years old.
220         }
221
222         if (exp >= 10) {
223             points += 5;
224         }
225         if (exp >= 20) {
226             points += 5;
227         }
228         if (exp >= 30) {
229             points += 5;
230         }
231         if (exp >= 40) {
232             points += 5;
233         }
234         if (exp >= 50) {
235             points += 5;
236         }
237         return points;
238     }
239
240     public static User getById(int id) {
241         return new User(id);
242     }
243
244     public EmailAddress[] getEmails() {
245         try {
246             PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id FROM emails WHERE memid=? AND deleted=0");
247             ps.setInt(1, id);
248             ResultSet rs = ps.executeQuery();
249             rs.last();
250             int count = rs.getRow();
251             EmailAddress[] data = new EmailAddress[count];
252             rs.beforeFirst();
253             for (int i = 0; i < data.length; i++) {
254                 if ( !rs.next()) {
255                     throw new Error("Internal sql api violation.");
256                 }
257                 data[i] = EmailAddress.getById(rs.getInt(1));
258             }
259             rs.close();
260             return data;
261         } catch (SQLException e) {
262             e.printStackTrace();
263         }
264
265         return null;
266     }
267
268     public Domain[] getDomains() {
269         try {
270             PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id FROM domains WHERE memid=? AND deleted IS NULL");
271             ps.setInt(1, id);
272             ResultSet rs = ps.executeQuery();
273             rs.last();
274             int count = rs.getRow();
275             Domain[] data = new Domain[count];
276             rs.beforeFirst();
277             for (int i = 0; i < data.length; i++) {
278                 if ( !rs.next()) {
279                     throw new Error("Internal sql api violation.");
280                 }
281                 data[i] = Domain.getById(rs.getInt(1));
282             }
283             rs.close();
284             return data;
285         } catch (SQLException e) {
286             e.printStackTrace();
287         }
288
289         return null;
290     }
291
292     public Certificate[] getCertificates() {
293         try {
294             PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT serial FROM certs WHERE memid=? AND revoked=0");
295             ps.setInt(1, id);
296             ResultSet rs = ps.executeQuery();
297             rs.last();
298             int count = rs.getRow();
299             Certificate[] data = new Certificate[count];
300             rs.beforeFirst();
301             for (int i = 0; i < data.length; i++) {
302                 if ( !rs.next()) {
303                     throw new Error("Internal sql api violation.");
304                 }
305                 data[i] = Certificate.getBySerial(rs.getString(1));
306             }
307             rs.close();
308             return data;
309         } catch (SQLException e) {
310             e.printStackTrace();
311         }
312
313         return null;
314     }
315
316     public boolean isValidDomain(String domainname) {
317         for (Domain d : getDomains()) {
318             String sfx = d.getSuffix();
319             if (domainname.equals(sfx) || domainname.endsWith("." + sfx)) {
320                 return true;
321             }
322         }
323         return false;
324     }
325
326     public boolean isValidEmail(String email) {
327         for (EmailAddress em : getEmails()) {
328             if (em.getAddress().equals(email)) {
329                 return true;
330             }
331         }
332         return false;
333     }
334
335     public boolean isValidName(String name) {
336         return getName().matches(name);
337     }
338
339     public void updateDefaultEmail(EmailAddress newMail) throws GigiApiException {
340         try {
341             EmailAddress[] adrs = getEmails();
342             for (int i = 0; i < adrs.length; i++) {
343                 if (adrs[i].getAddress().equals(newMail.getAddress())) {
344                     if ( !adrs[i].isVerified()) {
345                         throw new GigiApiException("Email not verified.");
346                     }
347                     PreparedStatement ps = DatabaseConnection.getInstance().prepare("UPDATE users SET email=? WHERE id=?");
348                     ps.setString(1, newMail.getAddress());
349                     ps.setInt(2, getId());
350                     ps.execute();
351                     email = newMail.getAddress();
352                     return;
353                 }
354             }
355             throw new GigiApiException("Given address not an address of the user.");
356         } catch (SQLException e) {
357             throw new GigiApiException(e);
358         }
359     }
360
361     public void deleteEmail(EmailAddress mail) throws GigiApiException {
362         if (getEmail().equals(mail.getAddress())) {
363             throw new GigiApiException("Can't delete user's default e-mail.");
364         }
365         EmailAddress[] emails = getEmails();
366         for (int i = 0; i < emails.length; i++) {
367             if (emails[i].getId() == mail.getId()) {
368                 try {
369                     PreparedStatement ps = DatabaseConnection.getInstance().prepare("UPDATE emails SET deleted=? WHERE id=?");
370                     ps.setDate(1, new Date(System.currentTimeMillis()));
371                     ps.setInt(2, mail.getId());
372                     ps.execute();
373                 } catch (SQLException e) {
374                     e.printStackTrace();
375                     throw new GigiApiException(e);
376                 }
377                 return;
378             }
379         }
380         throw new GigiApiException("Email not one of user's email addresses.");
381     }
382
383     public Assurance[] getReceivedAssurances() throws SQLException {
384         if (receivedAssurances == null) {
385             PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT * FROM notary WHERE `to`=? AND deleted=0");
386             query.setInt(1, getId());
387             ResultSet res = query.executeQuery();
388             res.last();
389             Assurance[] assurances = new Assurance[res.getRow()];
390             res.beforeFirst();
391             for (int i = 0; i < assurances.length; i++) {
392                 res.next();
393                 assurances[i] = new Assurance(res);
394             }
395             this.receivedAssurances = assurances;
396             return assurances;
397         }
398         return receivedAssurances;
399     }
400
401     public Assurance[] getMadeAssurances() throws SQLException {
402         if (madeAssurances == null) {
403             PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT * FROM notary WHERE `from`=? AND deleted=0");
404             query.setInt(1, getId());
405             ResultSet res = query.executeQuery();
406             res.last();
407             Assurance[] assurances = new Assurance[res.getRow()];
408             res.beforeFirst();
409             for (int i = 0; i < assurances.length; i++) {
410                 res.next();
411                 assurances[i] = new Assurance(res);
412             }
413             this.madeAssurances = assurances;
414             return assurances;
415         }
416         return madeAssurances;
417     }
418
419     public void invalidateMadeAssurances() {
420         madeAssurances = null;
421     }
422
423     public void invalidateReceivedAssurances() {
424         receivedAssurances = null;
425     }
426 }