AclDAO { protected void enrollClient(Configuration configuration, long clientId, long groupId) { long now = OffsetDateTime.now().toEpochSecond(); boolean enrolled = 0 < DSL.using(configuration) .fetchCount(MEMBERSHIPS, MEMBERSHIPS.GROUPID.eq(groupId).and( MEMBERSHIPS.CLIENTID.eq(clientId))); if (enrolled) { return; } String verificationHmac = rowHmacGenerator.computeRowHmac( MEMBERSHIPS.getName(), List.of(clientId, groupId)); DSL.using(configuration) .insertInto(MEMBERSHIPS) .set(MEMBERSHIPS.GROUPID, groupId) .set(MEMBERSHIPS.CLIENTID, clientId) .set(MEMBERSHIPS.CREATEDAT, now) .set(MEMBERSHIPS.UPDATEDAT, now) .set(MEMBERSHIPS.ROW_HMAC, verificationHmac) .execute(); } private  AclDAO(DSLContext dslContext, ClientDAOFactory clientDAOFactory, GroupDAOFactory groupDAOFactory,
                 SecretContentDAOFactory secretContentDAOFactory, SecretSeriesDAOFactory secretSeriesDAOFactory,
                 ClientMapper clientMapper, GroupMapper groupMapper, SecretSeriesMapper secretSeriesMapper,
                 SecretContentMapper secretContentMapper, RowHmacGenerator rowHmacGenerator,
                 KeywhizConfig config); void findAndAllowAccess(long secretId, long groupId, AuditLog auditLog, String user, Map<String, String> extraInfo); void findAndRevokeAccess(long secretId, long groupId, AuditLog auditLog, String user, Map<String, String> extraInfo); void findAndEnrollClient(long clientId, long groupId, AuditLog auditLog, String user, Map<String, String> extraInfo); void findAndEvictClient(long clientId, long groupId, AuditLog auditLog, String user, Map<String, String> extraInfo); ImmutableSet<SanitizedSecret> getSanitizedSecretsFor(Group group); Set<Group> getGroupsFor(Secret secret); Set<Group> getGroupsFor(Client client); Set<Client> getClientsFor(Group group); ImmutableSet<SanitizedSecret> getSanitizedSecretsFor(Client client); Set<Client> getClientsFor(Secret secret); Optional<SanitizedSecret> getSanitizedSecretFor(Client client, String secretName); List<SanitizedSecret> getBatchSanitizedSecretsFor(Client client, List<String> secretNames); Map<Long, List<Group>> getGroupsForSecrets(Set<Long> secretIdList);  }
@Test public void enrollsClients() { int before = membershipsTableSize(); aclDAO.enrollClient(jooqContext.configuration(), client1.getId(), group2.getId()); assertThat(membershipsTableSize()).isEqualTo(before + 1); }
@Test public void enrollsClientsOnlyOnce() { int before = membershipsTableSize(); aclDAO.enrollClient(jooqContext.configuration(), client1.getId(), group2.getId()); aclDAO.enrollClient(jooqContext.configuration(), client1.getId(), group2.getId()); assertThat(membershipsTableSize()).isEqualTo(before + 1); }
@Test public void membershipsHasReferentialIntegrity() { aclDAO.enrollClient(jooqContext.configuration(), client1.getId(), group1.getId()); aclDAO.enrollClient(jooqContext.configuration(), client2.getId(), group2.getId()); int before = membershipsTableSize(); groupDAO.deleteGroup(group1); assertThat(membershipsTableSize()).isEqualTo(before - 1); clientDAO.deleteClient(client2); assertThat(membershipsTableSize()).isEqualTo(before - 2); }