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