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