class AclDAO {

  public Optional<SanitizedSecret> getSanitizedSecretFor(Client client, String secretName) {
    checkNotNull(client);
    checkArgument(!secretName.isEmpty());

    SelectQuery<Record> query = dslContext.select(SECRETS.fields())
        .from(SECRETS)
        .join(ACCESSGRANTS).on(SECRETS.ID.eq(ACCESSGRANTS.SECRETID))
        .join(MEMBERSHIPS).on(ACCESSGRANTS.GROUPID.eq(MEMBERSHIPS.GROUPID))
        .join(CLIENTS).on(CLIENTS.ID.eq(MEMBERSHIPS.CLIENTID))
        .join(SECRETS_CONTENT).on(SECRETS_CONTENT.ID.eq(SECRETS.CURRENT))
        .where(CLIENTS.NAME.eq(client.getName())
            .and(SECRETS.CURRENT.isNotNull())
            .and(SECRETS.NAME.eq(secretName)))
        .limit(1)
        .getQuery();
    query.addSelect(SECRETS_CONTENT.CONTENT_HMAC);
    query.addSelect(SECRETS_CONTENT.CREATEDAT);
    query.addSelect(SECRETS_CONTENT.CREATEDBY);
    query.addSelect(SECRETS_CONTENT.METADATA);
    query.addSelect(SECRETS_CONTENT.EXPIRY);
    query.addSelect(ACCESSGRANTS.ROW_HMAC);
    query.addSelect(MEMBERSHIPS.ROW_HMAC);
    query.addSelect(MEMBERSHIPS.GROUPID);
    query.addSelect(CLIENTS.ROW_HMAC);
    query.addSelect(SECRETS.ROW_HMAC);
    return Optional.ofNullable(query.fetchOne())
        .map(row -> processSanitizedSecretRow(row, client));
  }

  private  AclDAO(DSLContext dslContext, ClientDAOFactory clientDAOFactory, GroupDAOFactory groupDAOFactory,
                 SecretContentDAOFactory secretContentDAOFactory, SecretSeriesDAOFactory secretSeriesDAOFactory,
                 ClientMapper clientMapper, GroupMapper groupMapper, SecretSeriesMapper secretSeriesMapper,
                 SecretContentMapper secretContentMapper, RowHmacGenerator rowHmacGenerator,
                 KeywhizConfig config);

}