Added the option to check if some voter have voted already.

Voter-Registry
Vladimir Eliezer Tokarev 2016-03-05 06:33:07 -08:00
parent 4d72d6083e
commit 6d807cdd4d
5 changed files with 101 additions and 136 deletions

View File

@ -1,23 +0,0 @@
package meerkat;
import java.util.List;
/**
* Provides the validation option for objects
* @param <T>
*/
public interface MessageValidator <T extends List<?>>
{
/**
* Throws ValidationError when no part of the object is valid else return the valid part
* @param object object which will be checked
* @return T object
*/
T validate(T object) throws ValidationError;
class ValidationError extends Exception {
public ValidationError(String message) {
super(message);
}
}
}

View File

@ -121,22 +121,28 @@ public class Registry implements VoterRegistry{
}};
bulletinBoardClient.readMessages(MessageCollectionUtils.generateFiltersFromTags(GroupsActionsTags),
new LatestMessagesCallBack(callback, signers));
new LatestMessagesCallBack(callback, signers, "getGroups"));
}
@Override
public void getPersonIDDetails(VoterID voterID, RegistryCallBack callback) {
List<String> GroupsActionsTags = new ArrayList<String>() {{
List<String> addVoterTags = new ArrayList<String>() {{
add(RegistryTags.ID_TAG + voterID.getId());
add(RegistryTags.VOTER_ENTRY_TAG);
}};
bulletinBoardClient.readMessages(MessageCollectionUtils.generateFiltersFromTags(GroupsActionsTags),
new LatestMessagesCallBack(callback, signers));
bulletinBoardClient.readMessages(MessageCollectionUtils.generateFiltersFromTags(addVoterTags),
new LatestMessagesCallBack(callback, signers, "getPersonIDDetails"));
}
@Override
public boolean hasVoted(VoterID voterId, RegistryCallBack callBack) {
return false;
public void hasVoted(VoterID voterId, RegistryCallBack callBack) {
List<String> setVotedTags = new ArrayList<String>() {{
add(RegistryTags.ID_TAG + voterId.getId());
add(RegistryTags.VOTE_ACTION_TAG);
}};
bulletinBoardClient.readMessages(MessageCollectionUtils.generateFiltersFromTags(setVotedTags),
new LatestMessagesCallBack(callBack, signers, "hasVoted"));
}
}

View File

@ -84,6 +84,6 @@ public interface VoterRegistry {
* @param callBack method that will be called with the when the result will be found
* @return true if voter had voted
*/
boolean hasVoted(VoterID voterId, RegistryCallBack callBack);
void hasVoted(VoterID voterId, RegistryCallBack callBack);
}

View File

@ -1,58 +1,42 @@
package meerkat.registry;
import com.google.common.util.concurrent.FutureCallback;
import meerkat.MessageValidator;
import meerkat.VoterRegistry.RegistryCallBack;
import meerkat.crypto.DigitalSignature;
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
import meerkat.protobuf.Crypto;
import meerkat.util.TimestampComparator;
import java.security.InvalidKeyException;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static meerkat.util.BulletinBoardUtils.GetListOfTags;
import static meerkat.util.BulletinBoardUtils.findTagWithPrefix;
/**
* TODO : add logging and verification of the messages
* TODO : add logging and verification of the messages by Arbel Peled
*/
/**
* Created by Vladimir Eliezer Tokarev on 2/19/2016.
* Gets latest data from given List<BulletinBoardMessage>
*/
public class LatestMessagesCallBack implements FutureCallback<List<BulletinBoardMessage>>, MessageValidator<List<BulletinBoardMessage>> {
public class LatestMessagesCallBack implements FutureCallback<List<BulletinBoardMessage>> {
public RegistryCallBack callback;
protected Collection<DigitalSignature> validators;
protected String type;
/**
* init MessagesCallBack
* @param callback voter registry callback object
* @param validators DigitalSignature object
*/
public LatestMessagesCallBack(RegistryCallBack callback, Collection<DigitalSignature> validators) {
public LatestMessagesCallBack(RegistryCallBack callback,
Collection<DigitalSignature> validators, String type) {
this.callback = callback;
this.validators = validators;
}
/**
* Checks if the given list have tags of type GROUP_ID_TAG or else
* @param msg List<BulletinBoardAPI.BulletinBoardMessage>
* @return true if the messages are with GROUP_ID_TAG tags
*/
private boolean isAddToGroupsList(List<BulletinBoardMessage> msg) {
List<String> tags = msg.get(0).getMsg().getTagList();
for (String tag : tags) {
if(tag.contains(RegistryTags.GROUP_ID_TAG))
{
return true;
}
}
return false;
this.type = type;
}
/**
@ -70,12 +54,16 @@ public class LatestMessagesCallBack implements FutureCallback<List<BulletinBoard
});
List<BulletinBoardMessage> messages = new ArrayList<BulletinBoardMessage>(){{add(lastAddedMessage);}};
if (isAddToGroupsList(msg)) {
callback.handleResult(GetListOfTags(messages, RegistryTags.GROUP_ID_TAG));
}
else {
callback.handleResult(lastAddedMessage);
switch (type){
case "getGroups" :
callback.handleResult(GetListOfTags(messages, RegistryTags.GROUP_ID_TAG));
break;
case "getPersonIDDetails" : callback.handleResult(lastAddedMessage);
break;
case "hasVoted" :
callback.handleResult(findTagWithPrefix(lastAddedMessage,
RegistryTags.VOTE_ACTION_TAG) != null);
break;
}
}
@ -87,51 +75,4 @@ public class LatestMessagesCallBack implements FutureCallback<List<BulletinBoard
public void onFailure(Throwable t) {
callback.handleFailure(t);
}
/**
* verify that the message is valid
* @param message BulletinBoardMessage instance
* @return true if the message is valid else false
*/
private boolean verifyMessage(BulletinBoardMessage message)
{
try {
int counter = 0;
for (Crypto.Signature signature : message.getSigList()) {
for (DigitalSignature digitalSignature : validators) {
if (signature.getSignerId().equals(digitalSignature.getSignerID()))
{
digitalSignature.initVerify(signature);
if(digitalSignature.verify())
{
counter++;
}
}
}
}
return counter == validators.size();
} catch (CertificateException | InvalidKeyException e) {
e.printStackTrace();
return false;
}
}
/**
* Gets all the valid messages from the list of bulletin board messages
* @param object object which will be checked
* @return List<BulletinBoardMessage>
* @throws ValidationError
*/
@Override
public List<BulletinBoardMessage> validate(List<BulletinBoardMessage> object) throws ValidationError {
List<BulletinBoardMessage> verifiedMessages = new ArrayList<>(object.size());
for (BulletinBoardMessage message : object)
{
if(verifyMessage(message))
{
verifiedMessages.add(message);
}
}
return verifiedMessages;
}
}

View File

@ -1,5 +1,4 @@
import com.google.common.util.concurrent.FutureCallback;
import com.google.protobuf.InvalidProtocolBufferException;
import junit.framework.TestCase;
import meerkat.Registry;
import meerkat.bulletinboard.AsyncBulletinBoardClient;
@ -15,6 +14,7 @@ import meerkat.protobuf.VoterRegistry.VoterInfo;
import meerkat.protobuf.Voting;
import meerkat.registry.MessageCollectionUtils;
import meerkat.registry.RegistryTags;
import org.junit.Test;
import java.io.InputStream;
import java.math.BigInteger;
@ -67,6 +67,7 @@ public class SimpleRegistryTest extends TestCase {
@Override
public void handleFailure(Throwable throwable) {
System.out.print(throwable);
}
}
@ -137,10 +138,16 @@ public class SimpleRegistryTest extends TestCase {
return registry;
}
private String generateString()
{
return new BigInteger(130, random).toString(32);
}
/**
* Checks if the creation of the registry have been successful
*/
public void testSimpleRegistryCreation() {
@Test
public void simpleRegistryCreation() {
try {
Registry registry = GetRegistry();
} catch (Exception e) {
@ -175,14 +182,30 @@ public class SimpleRegistryTest extends TestCase {
return counter;
}
/**
* Reads messages from bulletinBoardClient by given tags and return the callback handler
* object
*
* @param tags list of strings that represents tags
* @return DummyBulletinBoardCallBackHandler which method will be called
*/
private DummyBulletinBoardCallBackHandler readMessagesByTags(List<String> tags)
{
MessageFilterList filters = MessageCollectionUtils.generateFiltersFromTags(tags);
DummyBulletinBoardCallBackHandler bulletinHandler = new DummyBulletinBoardCallBackHandler();
bulletinBoardClient.readMessages(filters, bulletinHandler);
return bulletinHandler;
}
/**
* Test that add voter creates new correct bulletin board message and adds the voter
*/
public void testAddVoter() throws InvalidProtocolBufferException, InterruptedException {
@Test
public void testAddVoter() throws InterruptedException {
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
String id = new BigInteger(130, random).toString(32);
String data = new BigInteger(130, random).toString(32);
String id = generateString();
String data = generateString();
VoterInfo voterInfo = VoterInfo.newBuilder().setId(VoterID.newBuilder().setId(id)).setInfo(data).build();
Registry registry = GetRegistry();
@ -192,9 +215,7 @@ public class SimpleRegistryTest extends TestCase {
assertEquals(1, handler.counter );
List<String> tags = new ArrayList<String>(){{ add(RegistryTags.VOTER_ENTRY_TAG);}};
MessageFilterList filters = MessageCollectionUtils.generateFiltersFromTags(tags);
DummyBulletinBoardCallBackHandler bulletinHandler = new DummyBulletinBoardCallBackHandler();
bulletinBoardClient.readMessages(filters, bulletinHandler);
DummyBulletinBoardCallBackHandler bulletinHandler = readMessagesByTags(tags);
jobSemaphore.acquire();
@ -208,10 +229,11 @@ public class SimpleRegistryTest extends TestCase {
/**
* Test that set voted posts creates correct bulletin board message and sets that the user have been voted
*/
public void testSetVoted() throws InvalidProtocolBufferException, InterruptedException {
@Test
public void testSetVoted() throws InterruptedException {
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
String id = new BigInteger(130, random).toString(32);
String id = generateString();
VoterID voterInfo = VoterID.newBuilder().setId(id).build();
Registry registry = GetRegistry();
@ -221,9 +243,7 @@ public class SimpleRegistryTest extends TestCase {
assertEquals(1, handler.counter );
List<String> tags = new ArrayList<String>(){{ add(RegistryTags.VOTE_ACTION_TAG);}};
MessageFilterList filters = MessageCollectionUtils.generateFiltersFromTags(tags);
DummyBulletinBoardCallBackHandler bulletinHandler = new DummyBulletinBoardCallBackHandler();
bulletinBoardClient.readMessages(filters, bulletinHandler);
DummyBulletinBoardCallBackHandler bulletinHandler = readMessagesByTags(tags);
jobSemaphore.acquire();
@ -237,11 +257,12 @@ public class SimpleRegistryTest extends TestCase {
/**
* Test that get groups retrieves the right groups the user are in
*/
public void testAddToGroup() throws InvalidProtocolBufferException, InterruptedException {
@Test
public void testAddToGroup() throws InterruptedException {
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
String voterId = new BigInteger(130, random).toString(32);
String groupId = new BigInteger(130, random).toString(32);
String voterId = generateString();
String groupId = generateString();
VoterRegistry.VoterRegistryMessage voterInfo = VoterRegistry.VoterRegistryMessage.newBuilder()
.setVoterID(VoterID.newBuilder().setId(voterId))
.addGroupID(GroupID.newBuilder().setId(groupId)).build();
@ -250,12 +271,10 @@ public class SimpleRegistryTest extends TestCase {
registry.setVoterGroups(voterInfo, handler);
jobSemaphore.acquire();
assertEquals(1, handler.counter);
assertEquals("The callback handler hasn't been called yet", 1, handler.counter);
List<String> tags = new ArrayList<String>(){{add(RegistryTags.ADD_TO_GROUP_TAG);}};
MessageFilterList filters = MessageCollectionUtils.generateFiltersFromTags(tags);
DummyBulletinBoardCallBackHandler bulletinHandler = new DummyBulletinBoardCallBackHandler();
bulletinBoardClient.readMessages(filters, bulletinHandler);
DummyBulletinBoardCallBackHandler bulletinHandler = readMessagesByTags(tags);
jobSemaphore.acquire();
@ -270,12 +289,13 @@ public class SimpleRegistryTest extends TestCase {
/**
* Test that remove from group creates correct bulletin board message and removes the user from a group
*/
public void testGetGroups() throws InvalidProtocolBufferException, InterruptedException {
@Test
public void testGetGroups() throws InterruptedException {
DummyRegistryCallBackHandler<List<BulletinBoardMessage>> handler =
new DummyRegistryCallBackHandler<>();
String voterId = new BigInteger(130, random).toString(32);
String groupId = new BigInteger(130, random).toString(32);
String voterId = generateString();
String groupId = generateString();
VoterRegistry.VoterRegistryMessage voterInfo = VoterRegistry.VoterRegistryMessage.newBuilder()
.setVoterID(VoterID.newBuilder().setId(voterId))
.addGroupID(GroupID.newBuilder().setId(groupId)).build();
@ -286,7 +306,7 @@ public class SimpleRegistryTest extends TestCase {
registry.setVoterGroups(voterInfo, handler);
jobSemaphore.acquire();
assertEquals(1, handler.counter );
assertEquals("The callback handler hasn't been called yet", 1, handler.counter );
DummyRegistryCallBackHandler<List<String>> groupsHandler = new DummyRegistryCallBackHandler<>();
registry.getGroups(GroupID.newBuilder().setId(groupId).build(), groupsHandler);
@ -299,12 +319,13 @@ public class SimpleRegistryTest extends TestCase {
/**
* Test that the personal data outputted about the user is right
*/
public void testGetPersonalIDDetails() throws InvalidProtocolBufferException, InterruptedException {
@Test
public void testGetPersonalIDDetails() throws InterruptedException {
DummyRegistryCallBackHandler<List<BulletinBoardMessage>> handler =
new DummyRegistryCallBackHandler<>();
String id = new BigInteger(130, random).toString(32);
String data = new BigInteger(130, random).toString(32);
String id = generateString();
String data = generateString();
VoterInfo voterInfo = VoterInfo.newBuilder().
setId(VoterID.newBuilder().setId(id)).setInfo(data).build();
@ -312,14 +333,34 @@ public class SimpleRegistryTest extends TestCase {
registry.addVoter(voterInfo, handler);
jobSemaphore.acquire();
assertEquals(1, handler.counter );
assertEquals("The callback handler hasn't been called yet", 1, handler.counter );
DummyRegistryCallBackHandler<BulletinBoardMessage> personalHandler = new DummyRegistryCallBackHandler<>();
registry.getPersonIDDetails(VoterID.newBuilder().setId(id).build(), personalHandler);
jobSemaphore.acquire(1);
assertEquals(id, findTagWithPrefix(personalHandler.data, RegistryTags.ID_TAG));
assertTrue(findTagWithPrefix(personalHandler.data, data) != null);
assertEquals("The voter id doesn't match the created on ",
id, findTagWithPrefix(personalHandler.data, RegistryTags.ID_TAG));
assertTrue("The voter personal data can't be found.",
findTagWithPrefix(personalHandler.data, data) != null);
}
public void testHasVoted () throws InterruptedException {
DummyRegistryCallBackHandler<Boolean> handler = new DummyRegistryCallBackHandler<>();
String id = generateString();
VoterID voterInfo = VoterID.newBuilder().setId(id).build();
Registry registry = GetRegistry();
registry.setVoted(voterInfo, handler);
jobSemaphore.acquire();
assertEquals("The callback handler hasn't been called yet", 1, handler.counter);
DummyRegistryCallBackHandler<Boolean> personalHandler = new DummyRegistryCallBackHandler<>();
registry.hasVoted(VoterID.newBuilder().setId(id).build(), personalHandler);
jobSemaphore.acquire(1);
assertTrue("The voter hasn't voted yet.", personalHandler.data);
}
}