]> WPIA git - gigi.git/blobdiff - src/org/cacert/gigi/dbObjects/User.java
UPD: Removed small debug output
[gigi.git] / src / org / cacert / gigi / dbObjects / User.java
index 7a11cdb40b9a294a568c8c934f6d277f2d02f93b..c453465b505c36c460626c3ff149b83202225463 100644 (file)
@@ -1,22 +1,25 @@
 package org.cacert.gigi.dbObjects;
 
 import java.sql.Date;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
+import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 
 import org.cacert.gigi.GigiApiException;
 import org.cacert.gigi.database.DatabaseConnection;
+import org.cacert.gigi.database.GigiPreparedStatement;
+import org.cacert.gigi.database.GigiResultSet;
 import org.cacert.gigi.localisation.Language;
 import org.cacert.gigi.util.Notary;
 import org.cacert.gigi.util.PasswordHash;
 import org.cacert.gigi.util.PasswordStrengthChecker;
 
-public class User implements IdCachable {
-
-    private int id;
+public class User extends CertificateOwner {
 
     private Name name = new Name(null, null, null, null);
 
@@ -28,39 +31,34 @@ public class User implements IdCachable {
 
     private Locale locale;
 
-    private User(int id) {
-        this.id = id;
-        updateName(id);
-    }
-
-    private void updateName(int id) {
-        try {
-            PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `fname`, `lname`,`mname`, `suffix`, `dob`, `email`, `language` FROM `users` WHERE id=?");
-            ps.setInt(1, id);
-            ResultSet rs = ps.executeQuery();
-            if (rs.next()) {
-                name = new Name(rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4));
-                dob = rs.getDate(5);
-                email = rs.getString(6);
-                String localeStr = rs.getString(7);
-                if (localeStr == null || localeStr.equals("")) {
-                    locale = Locale.getDefault();
-                } else {
-                    locale = Language.getLocaleFromString(localeStr);
-                }
-            }
-            rs.close();
-        } catch (SQLException e) {
-            e.printStackTrace();
+    private Set<Group> groups = new HashSet<>();
+
+    protected User(GigiResultSet rs) {
+        super(rs.getInt("id"));
+        updateName(rs);
+    }
+
+    private void updateName(GigiResultSet rs) {
+        name = new Name(rs.getString("fname"), rs.getString("lname"), rs.getString("mname"), rs.getString("suffix"));
+        dob = rs.getDate("dob");
+        email = rs.getString("email");
+        String localeStr = rs.getString("language");
+        if (localeStr == null || localeStr.equals("")) {
+            locale = Locale.getDefault();
+        } else {
+            locale = Language.getLocaleFromString(localeStr);
+        }
+        GigiPreparedStatement psg = DatabaseConnection.getInstance().prepare("SELECT permission FROM user_groups WHERE user=? AND deleted is NULL");
+        psg.setInt(1, rs.getInt("id"));
+        GigiResultSet rs2 = psg.executeQuery();
+        while (rs2.next()) {
+            groups.add(Group.getByString(rs2.getString(1)));
         }
+        rs2.close();
     }
 
     public User() {}
 
-    public int getId() {
-        return id;
-    }
-
     public String getFname() {
         return name.fname;
     }
@@ -105,10 +103,6 @@ public class User implements IdCachable {
         this.email = email;
     }
 
-    public void setId(int id) {
-        this.id = id;
-    }
-
     public void setFname(String fname) {
         this.name.fname = fname;
     }
@@ -117,11 +111,9 @@ public class User implements IdCachable {
         this.name.lname = lname;
     }
 
-    public void insert(String password) throws SQLException {
-        if (id != 0) {
-            throw new Error("refusing to insert");
-        }
-        PreparedStatement query = DatabaseConnection.getInstance().prepare("insert into `users` set `email`=?, `password`=?, " + "`fname`=?, `mname`=?, `lname`=?, " + "`suffix`=?, `dob`=?, `created`=NOW(), locked=0, `language`=?");
+    public void insert(String password) {
+        int id = super.insert();
+        GigiPreparedStatement query = DatabaseConnection.getInstance().prepare("insert into `users` set `email`=?, `password`=?, " + "`fname`=?, `mname`=?, `lname`=?, " + "`suffix`=?, `dob`=?, `language`=?, id=?");
         query.setString(1, email);
         query.setString(2, PasswordHash.hash(password));
         query.setString(3, name.fname);
@@ -130,38 +122,35 @@ public class User implements IdCachable {
         query.setString(6, name.suffix);
         query.setDate(7, new java.sql.Date(dob.getTime()));
         query.setString(8, locale.toString());
-        synchronized (User.class) {
-            query.execute();
-            id = DatabaseConnection.lastInsertId(query);
-            myCache.put(this);
-        }
+        query.setInt(9, id);
+        query.execute();
     }
 
     public void changePassword(String oldPass, String newPass) throws GigiApiException {
-        try {
-            PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `password` FROM users WHERE id=?");
-            ps.setInt(1, id);
-            ResultSet rs = ps.executeQuery();
-            if ( !rs.next()) {
-                throw new GigiApiException("User not found... very bad.");
-            }
-            if ( !PasswordHash.verifyHash(oldPass, rs.getString(1))) {
-                throw new GigiApiException("Old password does not match.");
-            }
-            rs.close();
-            PasswordStrengthChecker.assertStrongPassword(newPass, this);
-            ps = DatabaseConnection.getInstance().prepare("UPDATE users SET `password`=? WHERE id=?");
-            ps.setString(1, PasswordHash.hash(newPass));
-            ps.setInt(2, id);
-            if (ps.executeUpdate() != 1) {
-                throw new GigiApiException("Password update failed.");
-            }
-        } catch (SQLException e) {
-            throw new GigiApiException(e);
+        GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `password` FROM users WHERE id=?");
+        ps.setInt(1, getId());
+        GigiResultSet rs = ps.executeQuery();
+        if ( !rs.next()) {
+            throw new GigiApiException("User not found... very bad.");
+        }
+        if (PasswordHash.verifyHash(oldPass, rs.getString(1)) == null) {
+            throw new GigiApiException("Old password does not match.");
+        }
+        rs.close();
+        PasswordStrengthChecker.assertStrongPassword(newPass, this);
+        ps = DatabaseConnection.getInstance().prepare("UPDATE users SET `password`=? WHERE id=?");
+        ps.setString(1, PasswordHash.hash(newPass));
+        ps.setInt(2, getId());
+        if (ps.executeUpdate() != 1) {
+            throw new GigiApiException("Password update failed.");
         }
     }
 
-    public boolean canAssure() throws SQLException {
+    public void setName(Name name) {
+        this.name = name;
+    }
+
+    public boolean canAssure() {
         if ( !isOfAge(14)) { // PoJAM
             return false;
         }
@@ -173,10 +162,10 @@ public class User implements IdCachable {
 
     }
 
-    public boolean hasPassedCATS() throws SQLException {
-        PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT 1 FROM `cats_passed` where `user_id`=?");
-        query.setInt(1, id);
-        ResultSet rs = query.executeQuery();
+    public boolean hasPassedCATS() {
+        GigiPreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT 1 FROM `cats_passed` where `user_id`=?");
+        query.setInt(1, getId());
+        GigiResultSet rs = query.executeQuery();
         if (rs.next()) {
             return true;
         } else {
@@ -184,10 +173,10 @@ public class User implements IdCachable {
         }
     }
 
-    public int getAssurancePoints() throws SQLException {
-        PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT sum(points) FROM `notary` where `to`=? AND `deleted`=0");
-        query.setInt(1, id);
-        ResultSet rs = query.executeQuery();
+    public int getAssurancePoints() {
+        GigiPreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT sum(points) FROM `notary` where `to`=? AND `deleted` is NULL");
+        query.setInt(1, getId());
+        GigiResultSet rs = query.executeQuery();
         int points = 0;
         if (rs.next()) {
             points = rs.getInt(1);
@@ -196,10 +185,10 @@ public class User implements IdCachable {
         return points;
     }
 
-    public int getExperiencePoints() throws SQLException {
-        PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT count(*) FROM `notary` where `from`=? AND `deleted`=0");
-        query.setInt(1, id);
-        ResultSet rs = query.executeQuery();
+    public int getExperiencePoints() {
+        GigiPreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT count(*) FROM `notary` where `from`=? AND `deleted` is NULL");
+        query.setInt(1, getId());
+        GigiResultSet rs = query.executeQuery();
         int points = 0;
         if (rs.next()) {
             points = rs.getInt(1) * 2;
@@ -226,10 +215,9 @@ public class User implements IdCachable {
      * Gets the maximum allowed points NOW. Note that an assurance needs to
      * re-check PoJam as it has taken place in the past.
      * 
-     * @return the maximal points
-     * @throws SQLException
+     * @return the maximal points @
      */
-    public int getMaxAssurePoints() throws SQLException {
+    public int getMaxAssurePoints() {
         if ( !isOfAge(18)) {
             return 10; // PoJAM
         }
@@ -266,121 +254,26 @@ public class User implements IdCachable {
         return System.currentTimeMillis() >= c.getTime().getTime();
     }
 
-    public EmailAddress[] getEmails() {
-        try {
-            PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id FROM emails WHERE memid=? AND deleted=0");
-            ps.setInt(1, id);
-            ResultSet rs = ps.executeQuery();
-            rs.last();
-            int count = rs.getRow();
-            EmailAddress[] data = new EmailAddress[count];
-            rs.beforeFirst();
-            for (int i = 0; i < data.length; i++) {
-                if ( !rs.next()) {
-                    throw new Error("Internal sql api violation.");
-                }
-                data[i] = EmailAddress.getById(rs.getInt(1));
-            }
-            rs.close();
-            return data;
-        } catch (SQLException e) {
-            e.printStackTrace();
-        }
-
-        return null;
-    }
-
-    public Domain[] getDomains() {
-        try {
-            PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id FROM domains WHERE memid=? AND deleted IS NULL");
-            ps.setInt(1, id);
-            ResultSet rs = ps.executeQuery();
-            rs.last();
-            int count = rs.getRow();
-            Domain[] data = new Domain[count];
-            rs.beforeFirst();
-            for (int i = 0; i < data.length; i++) {
-                if ( !rs.next()) {
-                    throw new Error("Internal sql api violation.");
-                }
-                data[i] = Domain.getById(rs.getInt(1));
-            }
-            rs.close();
-            return data;
-        } catch (SQLException e) {
-            e.printStackTrace();
-        }
-
-        return null;
-    }
-
-    public Certificate[] getCertificates() {
-        try {
-            PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT serial FROM certs WHERE memid=? AND revoked=0");
-            ps.setInt(1, id);
-            ResultSet rs = ps.executeQuery();
-            rs.last();
-            int count = rs.getRow();
-            Certificate[] data = new Certificate[count];
-            rs.beforeFirst();
-            for (int i = 0; i < data.length; i++) {
-                if ( !rs.next()) {
-                    throw new Error("Internal sql api violation.");
-                }
-                data[i] = Certificate.getBySerial(rs.getString(1));
-            }
-            rs.close();
-            return data;
-        } catch (SQLException e) {
-            e.printStackTrace();
-        }
-
-        return null;
-    }
-
-    public boolean isValidDomain(String domainname) {
-        for (Domain d : getDomains()) {
-            String sfx = d.getSuffix();
-            if (domainname.equals(sfx) || domainname.endsWith("." + sfx)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public boolean isValidEmail(String email) {
-        for (EmailAddress em : getEmails()) {
-            if (em.getAddress().equals(email)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
     public boolean isValidName(String name) {
         return getName().matches(name);
     }
 
     public void updateDefaultEmail(EmailAddress newMail) throws GigiApiException {
-        try {
-            EmailAddress[] adrs = getEmails();
-            for (int i = 0; i < adrs.length; i++) {
-                if (adrs[i].getAddress().equals(newMail.getAddress())) {
-                    if ( !adrs[i].isVerified()) {
-                        throw new GigiApiException("Email not verified.");
-                    }
-                    PreparedStatement ps = DatabaseConnection.getInstance().prepare("UPDATE users SET email=? WHERE id=?");
-                    ps.setString(1, newMail.getAddress());
-                    ps.setInt(2, getId());
-                    ps.execute();
-                    email = newMail.getAddress();
-                    return;
+        EmailAddress[] adrs = getEmails();
+        for (int i = 0; i < adrs.length; i++) {
+            if (adrs[i].getAddress().equals(newMail.getAddress())) {
+                if ( !adrs[i].isVerified()) {
+                    throw new GigiApiException("Email not verified.");
                 }
+                GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("UPDATE users SET email=? WHERE id=?");
+                ps.setString(1, newMail.getAddress());
+                ps.setInt(2, getId());
+                ps.execute();
+                email = newMail.getAddress();
+                return;
             }
-            throw new GigiApiException("Given address not an address of the user.");
-        } catch (SQLException e) {
-            throw new GigiApiException(e);
         }
+        throw new GigiApiException("Given address not an address of the user.");
     }
 
     public void deleteEmail(EmailAddress mail) throws GigiApiException {
@@ -390,26 +283,21 @@ public class User implements IdCachable {
         EmailAddress[] emails = getEmails();
         for (int i = 0; i < emails.length; i++) {
             if (emails[i].getId() == mail.getId()) {
-                try {
-                    PreparedStatement ps = DatabaseConnection.getInstance().prepare("UPDATE emails SET deleted=? WHERE id=?");
-                    ps.setDate(1, new Date(System.currentTimeMillis()));
-                    ps.setInt(2, mail.getId());
-                    ps.execute();
-                } catch (SQLException e) {
-                    e.printStackTrace();
-                    throw new GigiApiException(e);
-                }
+                GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("UPDATE emails SET deleted=? WHERE id=?");
+                ps.setDate(1, new Date(System.currentTimeMillis()));
+                ps.setInt(2, mail.getId());
+                ps.execute();
                 return;
             }
         }
         throw new GigiApiException("Email not one of user's email addresses.");
     }
 
-    public Assurance[] getReceivedAssurances() throws SQLException {
+    public Assurance[] getReceivedAssurances() {
         if (receivedAssurances == null) {
-            PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT * FROM notary WHERE `to`=? AND deleted=0");
+            GigiPreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT * FROM notary WHERE `to`=? AND deleted IS NULL");
             query.setInt(1, getId());
-            ResultSet res = query.executeQuery();
+            GigiResultSet res = query.executeQuery();
             res.last();
             Assurance[] assurances = new Assurance[res.getRow()];
             res.beforeFirst();
@@ -423,11 +311,11 @@ public class User implements IdCachable {
         return receivedAssurances;
     }
 
-    public Assurance[] getMadeAssurances() throws SQLException {
+    public Assurance[] getMadeAssurances() {
         if (madeAssurances == null) {
-            PreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT * FROM notary WHERE `from`=? AND deleted=0");
+            GigiPreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT * FROM notary WHERE `from`=? AND deleted is NULL");
             query.setInt(1, getId());
-            ResultSet res = query.executeQuery();
+            GigiResultSet res = query.executeQuery();
             res.last();
             Assurance[] assurances = new Assurance[res.getRow()];
             res.beforeFirst();
@@ -449,12 +337,12 @@ public class User implements IdCachable {
         receivedAssurances = null;
     }
 
-    public void updateUserData() throws SQLException, GigiApiException {
+    public void updateUserData() throws GigiApiException {
         synchronized (Notary.class) {
             if (getAssurancePoints() != 0) {
                 throw new GigiApiException("No change after assurance allowed.");
             }
-            PreparedStatement update = DatabaseConnection.getInstance().prepare("UPDATE users SET fname=?, lname=?, mname=?, suffix=?, dob=? WHERE id=?");
+            GigiPreparedStatement update = DatabaseConnection.getInstance().prepare("UPDATE users SET fname=?, lname=?, mname=?, suffix=?, dob=? WHERE id=?");
             update.setString(1, getFname());
             update.setString(2, getLname());
             update.setString(3, getMname());
@@ -474,45 +362,117 @@ public class User implements IdCachable {
 
     }
 
-    public boolean wantsDirectoryListing() throws SQLException {
-        PreparedStatement get = DatabaseConnection.getInstance().prepare("SELECT listme FROM users WHERE id=?");
+    public boolean wantsDirectoryListing() {
+        GigiPreparedStatement get = DatabaseConnection.getInstance().prepare("SELECT listme FROM users WHERE id=?");
         get.setInt(1, getId());
-        ResultSet exec = get.executeQuery();
+        GigiResultSet exec = get.executeQuery();
         exec.next();
         return exec.getBoolean("listme");
     }
 
-    public String getContactInformation() throws SQLException {
-        PreparedStatement get = DatabaseConnection.getInstance().prepare("SELECT contactinfo FROM users WHERE id=?");
+    public String getContactInformation() {
+        GigiPreparedStatement get = DatabaseConnection.getInstance().prepare("SELECT contactinfo FROM users WHERE id=?");
         get.setInt(1, getId());
-        ResultSet exec = get.executeQuery();
+        GigiResultSet exec = get.executeQuery();
         exec.next();
         return exec.getString("contactinfo");
     }
 
-    public void setDirectoryListing(boolean on) throws SQLException {
-        PreparedStatement update = DatabaseConnection.getInstance().prepare("UPDATE users SET listme = ? WHERE id = ?");
+    public void setDirectoryListing(boolean on) {
+        GigiPreparedStatement update = DatabaseConnection.getInstance().prepare("UPDATE users SET listme = ? WHERE id = ?");
         update.setBoolean(1, on);
         update.setInt(2, getId());
         update.executeUpdate();
     }
 
-    public void setContactInformation(String contactInfo) throws SQLException {
-        PreparedStatement update = DatabaseConnection.getInstance().prepare("UPDATE users SET contactinfo = ? WHERE id = ?");
+    public void setContactInformation(String contactInfo) {
+        GigiPreparedStatement update = DatabaseConnection.getInstance().prepare("UPDATE users SET contactinfo = ? WHERE id = ?");
         update.setString(1, contactInfo);
         update.setInt(2, getId());
         update.executeUpdate();
     }
 
-    private static ObjectCache<User> myCache = new ObjectCache<>();
+    public boolean isInGroup(Group g) {
+        return groups.contains(g);
+    }
+
+    public Set<Group> getGroups() {
+        return Collections.unmodifiableSet(groups);
+    }
 
-    public static User getById(int id) {
-        User u = myCache.get(id);
-        if (u == null) {
-            synchronized (User.class) {
-                myCache.put(u = new User(id));
-            }
+    public void grantGroup(User granter, Group toGrant) {
+        groups.add(toGrant);
+        GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("INSERT INTO user_groups SET user=?, permission=?, grantedby=?");
+        ps.setInt(1, getId());
+        ps.setString(2, toGrant.getDatabaseName());
+        ps.setInt(3, granter.getId());
+        ps.execute();
+    }
+
+    public void revokeGroup(User revoker, Group toRevoke) {
+        groups.remove(toRevoke);
+        GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("UPDATE user_groups SET deleted=CURRENT_TIMESTAMP, revokedby=? WHERE deleted is NULL AND permission=? AND user=?");
+        ps.setInt(1, revoker.getId());
+        ps.setString(2, toRevoke.getDatabaseName());
+        ps.setInt(3, getId());
+        ps.execute();
+    }
+
+    public List<Organisation> getOrganisations() {
+        List<Organisation> orgas = new ArrayList<>();
+        GigiPreparedStatement query = DatabaseConnection.getInstance().prepare("SELECT orgid FROM org_admin WHERE `memid`=? AND deleted is NULL");
+        query.setInt(1, getId());
+        GigiResultSet res = query.executeQuery();
+
+        while (res.next()) {
+            orgas.add(Organisation.getById(res.getInt(1)));
+        }
+        return orgas;
+    }
+
+    public static synchronized User getById(int id) {
+        CertificateOwner co = CertificateOwner.getById(id);
+        if (co instanceof User) {
+            return (User) co;
+        }
+        return null;
+    }
+
+    public static User getByEmail(String mail) {
+        GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT users.id FROM users inner join certOwners on certOwners.id=users.id WHERE email=? AND deleted is null");
+        ps.setString(1, mail);
+        GigiResultSet rs = ps.executeQuery();
+        if ( !rs.next()) {
+            return null;
         }
-        return u;
+        return User.getById(rs.getInt(1));
     }
+
+    public static User[] findByEmail(String mail) {
+        LinkedList<User> results = new LinkedList<User>();
+        GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT users.id FROM users inner join certOwners on certOwners.id=users.id WHERE users.email LIKE ? AND deleted is null GROUP BY users.id ASC LIMIT 100");
+        ps.setString(1, mail);
+        GigiResultSet rs = ps.executeQuery();
+        while (rs.next()) {
+            results.add(User.getById(rs.getInt(1)));
+        }
+        return results.toArray(new User[results.size()]);
+    }
+
+    public boolean canIssue(CertificateProfile p) {
+        switch (p.getCAId()) {
+        case 0:
+            return true;
+        case 1:
+            return getAssurancePoints() > 50;
+        case 2:
+            return getAssurancePoints() > 50 && isInGroup(Group.getByString("codesigning"));
+        case 3:
+        case 4:
+            return false; // has an orga
+        default:
+            return false;
+        }
+    }
+
 }