--- /dev/null
+package org.cacert.gigi.dbObjects;
+
+import java.util.HashMap;
+
+public class Group {
+
+ private static HashMap<String, Group> cache = new HashMap<>();
+
+ private final String dbName;
+
+ private Group(String name) {
+ dbName = name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((dbName == null) ? 0 : dbName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Group other = (Group) obj;
+ if (dbName == null) {
+ if (other.dbName != null) {
+ return false;
+ }
+ } else if ( !dbName.equals(other.dbName)) {
+ return false;
+ }
+ return true;
+ }
+
+ public static synchronized Group getByString(String name) {
+ Group g = cache.get(name);
+ if (g == null) {
+ g = new Group(name);
+ cache.put(name, g);
+ }
+ return g;
+ }
+
+ public String getDatabaseName() {
+ return dbName;
+ }
+}
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Locale;
+import java.util.Set;
import org.cacert.gigi.GigiApiException;
import org.cacert.gigi.database.DatabaseConnection;
private Locale locale;
+ private Set<Group> groups = new HashSet<>();
+
private User(int id) {
this.id = id;
updateName(id);
}
}
rs.close();
+ PreparedStatement psg = DatabaseConnection.getInstance().prepare("SELECT permission FROM user_groups WHERE user=? AND deleted is NULL");
+ psg.setInt(1, id);
+ ResultSet rs2 = psg.executeQuery();
+ while (rs2.next()) {
+ groups.add(Group.getByString(rs2.getString(1)));
+ }
+ rs2.close();
} catch (SQLException e) {
e.printStackTrace();
}
update.executeUpdate();
}
+ public boolean isInGroup(Group g) {
+ return groups.contains(g);
+ }
+
+ public Set<Group> getGroups() {
+ return Collections.unmodifiableSet(groups);
+ }
+
+ public void grantGroup(User granter, Group toGrant) throws GigiApiException {
+ groups.add(toGrant);
+ try {
+ PreparedStatement 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();
+ } catch (SQLException e) {
+ throw new GigiApiException(e);
+ }
+ }
+
+ public void revokeGroup(User revoker, Group toRevoke) throws GigiApiException {
+ groups.remove(toRevoke);
+ try {
+ PreparedStatement 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();
+ } catch (SQLException e) {
+ throw new GigiApiException(e);
+ }
+ }
+
private static ObjectCache<User> myCache = new ObjectCache<>();
public static synchronized User getById(int id) {
--- /dev/null
+package org.cacert.gigi;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+
+import org.cacert.gigi.database.DatabaseConnection;
+import org.cacert.gigi.dbObjects.Group;
+import org.cacert.gigi.dbObjects.ObjectCache;
+import org.cacert.gigi.dbObjects.User;
+import org.cacert.gigi.testUtils.ManagedTest;
+import org.junit.Test;
+
+public class TestUserGroupMembership extends ManagedTest {
+
+ private final Group ttpGroup = Group.getByString("ttp-assuer");
+
+ private final Group supporter = Group.getByString("supporter");
+
+ @Test
+ public void testAddObject() throws GigiApiException, SQLException {
+ User u = User.getById(createVerifiedUser("fname", "lname", createUniqueName() + "@example.org", TEST_PASSWORD));
+
+ User granter = User.getById(createVerifiedUser("grFname", "lname", createUniqueName() + "@example.org", TEST_PASSWORD));
+ assertBehavesEmpty(u);
+
+ u.grantGroup(granter, ttpGroup);
+ assertBehavesTtpGroup(u);
+
+ ObjectCache.clearAllCaches();
+ User u2 = User.getById(u.getId());
+
+ assertThat(u2, is(not(sameInstance(u))));
+ assertBehavesTtpGroup(u2);
+
+ ResultSet rs = fetchGroupRowsFor(u);
+
+ assertTrue(rs.next());
+ assertEquals(0, rs.getInt("revokedby"));
+ assertEquals(granter.getId(), rs.getInt("grantedby"));
+ assertEquals(ttpGroup.getDatabaseName(), rs.getString("permission"));
+
+ assertNull(rs.getDate("deleted"));
+ assertNotNull(rs.getDate("granted"));
+
+ assertFalse(rs.next());
+ }
+
+ @Test
+ public void testRemoveObject() throws GigiApiException, SQLException {
+ User u = User.getById(createVerifiedUser("fname", "lname", createUniqueName() + "@example.org", TEST_PASSWORD));
+
+ User granter = User.getById(createVerifiedUser("grFname", "lname", createUniqueName() + "@example.org", TEST_PASSWORD));
+
+ assertBehavesEmpty(u);
+ u.grantGroup(granter, ttpGroup);
+ assertBehavesTtpGroup(u);
+ u.revokeGroup(granter, ttpGroup);
+ assertBehavesEmpty(u);
+
+ ObjectCache.clearAllCaches();
+ User u2 = User.getById(u.getId());
+ assertThat(u2, is(not(sameInstance(u))));
+ assertBehavesEmpty(u);
+
+ ResultSet rs = fetchGroupRowsFor(u);
+ assertTrue(rs.next());
+ assertEquals(granter.getId(), rs.getInt("revokedby"));
+ assertEquals(granter.getId(), rs.getInt("grantedby"));
+ assertEquals(ttpGroup.getDatabaseName(), rs.getString("permission"));
+
+ assertNotNull(rs.getDate("deleted"));
+ assertNotNull(rs.getDate("granted"));
+
+ assertFalse(rs.next());
+ }
+
+ private ResultSet fetchGroupRowsFor(User u) throws SQLException {
+ PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT * FROM user_groups WHERE user=?");
+ ps.setInt(1, u.getId());
+ ResultSet rs = ps.executeQuery();
+ return rs;
+ }
+
+ private void assertBehavesEmpty(User u) {
+ assertEquals(Collections.emptySet(), u.getGroups());
+ assertFalse(u.isInGroup(ttpGroup));
+ assertFalse(u.isInGroup(supporter));
+ }
+
+ private void assertBehavesTtpGroup(User u) {
+ assertEquals(new HashSet<>(Arrays.asList(ttpGroup)), u.getGroups());
+ assertTrue(u.isInGroup(ttpGroup));
+ assertFalse(u.isInGroup(supporter));
+ }
+}