diff --git a/src/main/java/org/rulez/demokracia/pdengine/ADAAssuranceManager.java b/src/main/java/org/rulez/demokracia/pdengine/ADAAssuranceManager.java new file mode 100644 index 00000000..bd565f5d --- /dev/null +++ b/src/main/java/org/rulez/demokracia/pdengine/ADAAssuranceManager.java @@ -0,0 +1,12 @@ +package org.rulez.demokracia.pdengine; + +import java.util.List; + +public class ADAAssuranceManager implements AssuranceManager{ + + @Override + public List getAssurances(final String proxyId) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/main/java/org/rulez/demokracia/pdengine/AssuranceManager.java b/src/main/java/org/rulez/demokracia/pdengine/AssuranceManager.java new file mode 100644 index 00000000..e9f6cf08 --- /dev/null +++ b/src/main/java/org/rulez/demokracia/pdengine/AssuranceManager.java @@ -0,0 +1,7 @@ +package org.rulez.demokracia.pdengine; + +import java.util.List; + +public interface AssuranceManager { + List getAssurances(String proxyId); +} diff --git a/src/main/java/org/rulez/demokracia/pdengine/CastVote.java b/src/main/java/org/rulez/demokracia/pdengine/CastVote.java index 0a0f1ced..35f566cb 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/CastVote.java +++ b/src/main/java/org/rulez/demokracia/pdengine/CastVote.java @@ -8,7 +8,6 @@ public class CastVote extends CastVoteEntity implements CastVoteInterface { private static final long serialVersionUID = 1L; - private static final String DELIMITER = "|"; public CastVote(final String proxyId, final List preferences) { super(); @@ -17,6 +16,14 @@ public CastVote(final String proxyId, final List preferences) { secretId = RandomUtils.createRandomKey(); } + public CastVote( + final String proxyId, final List preferences, + final List assurances + ) { + this(proxyId, preferences); + this.assurances = assurances; + } + @Override public List getPreferences() { return preferences; @@ -24,18 +31,19 @@ public List getPreferences() { @Override public List getAssurances() { - throw new UnsupportedOperationException(); + return assurances; } public String contentToBeSigned() { final StringBuilder str = new StringBuilder(); + final String delimiter = "|"; - str.append(proxyId).append(DELIMITER) - .append(secretId).append(DELIMITER); + str.append(proxyId).append(delimiter) + .append(secretId).append(delimiter); for (final RankedChoice rc : preferences) - str.append(rc.id).append(DELIMITER) - .append(rc.choiceId).append(DELIMITER) - .append(rc.rank).append(DELIMITER); + str.append(rc.id).append(delimiter) + .append(rc.choiceId).append(delimiter) + .append(rc.rank).append(delimiter); return str.toString(); } diff --git a/src/main/java/org/rulez/demokracia/pdengine/IVoteManager.java b/src/main/java/org/rulez/demokracia/pdengine/IVoteManager.java index a5d8203a..64d51821 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/IVoteManager.java +++ b/src/main/java/org/rulez/demokracia/pdengine/IVoteManager.java @@ -13,8 +13,10 @@ public interface IVoteManager { - static IVoteManager getVoteManager(final WebServiceContext wsContext) { - return VoteManagerUtils.getVoteManager(wsContext); + static IVoteManager getVoteManager( + final WebServiceContext wsContext, final AssuranceManager assuranceManager + ) { + return VoteManagerUtils.getVoteManager(wsContext, assuranceManager); } WebServiceContext getWsContext(); @@ -66,4 +68,10 @@ void setVoteParameters( final VoteAdminInfo adminInfo, final VoteParameters voteParameters ); + List getAssurances(); + + static AssuranceManager getAssuranceManager() { + return new ADAAssuranceManager(); + } + } diff --git a/src/main/java/org/rulez/demokracia/pdengine/VoteManagerUtils.java b/src/main/java/org/rulez/demokracia/pdengine/VoteManagerUtils.java index d3fd09ff..441c9e1f 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/VoteManagerUtils.java +++ b/src/main/java/org/rulez/demokracia/pdengine/VoteManagerUtils.java @@ -10,13 +10,11 @@ final public class VoteManagerUtils { private static Map registry = new HashMap<>(); - private VoteManagerUtils() { - } - - public static IVoteManager getVoteManager(final WebServiceContext wsContext) { - if (!registry.containsKey(wsContext)) { - registry.put(wsContext, new VoteRegistry(wsContext)); - } + public static IVoteManager getVoteManager( + final WebServiceContext wsContext, final AssuranceManager assuranceManager + ) { + if (!registry.containsKey(wsContext)) + registry.put(wsContext, new VoteRegistry(wsContext, assuranceManager)); return registry.get(wsContext); } } diff --git a/src/main/java/org/rulez/demokracia/pdengine/VoteRegistry.java b/src/main/java/org/rulez/demokracia/pdengine/VoteRegistry.java index a1d88477..4f823af1 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/VoteRegistry.java +++ b/src/main/java/org/rulez/demokracia/pdengine/VoteRegistry.java @@ -12,46 +12,46 @@ public class VoteRegistry extends ChoiceManager implements IVoteManager { - public VoteRegistry(final WebServiceContext wsContext) { + private final AssuranceManager assuranceManager; + + public VoteRegistry( + final WebServiceContext wsContext, final AssuranceManager assuranceManager + ) { super(wsContext); + this.assuranceManager = assuranceManager; } @Override public String obtainBallot(final String identifier, final String adminKey) { - Vote vote = getVote(identifier); + final Vote vote = getVote(identifier); vote.checkAdminKey(adminKey); - if (adminKey.equals(vote.getAdminKey())) { + if (adminKey.equals(vote.getAdminKey())) vote.increaseRecordedBallots("admin"); - } else { - if (getWsContext().getUserPrincipal() == null) { + else { + if (getWsContext().getUserPrincipal() == null) throw new IllegalArgumentException( "Simple user is not authenticated, cannot issue any ballot." ); - } - if (!userHasAllAssurance(vote.getNeededAssurances())) { + if (!userHasAllAssurance(vote.getNeededAssurances())) throw new IllegalArgumentException( "The user does not have all of the needed assurances." ); - } - if (vote.getRecordedBallotsCount(getWsUserName()).intValue() > 0) { + if (vote.getRecordedBallotsCount(getWsUserName()).intValue() > 0) throw new IllegalArgumentException("This user already have a ballot."); - } vote.increaseRecordedBallots(getWsUserName()); } - String ballot = RandomUtils.createRandomKey(); + final String ballot = RandomUtils.createRandomKey(); vote.addBallot(ballot); return ballot; } public boolean userHasAllAssurance(final List neededAssuranceList) { - for (String neededAssurance : neededAssuranceList) { - if (!hasAssurance(neededAssurance)) { + for (final String neededAssurance : neededAssuranceList) + if (!hasAssurance(neededAssurance)) return false; - } - } return true; } @@ -59,7 +59,7 @@ public boolean userHasAllAssurance(final List neededAssuranceList) { public CastVote castVote( final String voteId, final String ballot, final List theVote ) { - Vote vote = getVote(voteId); + final Vote vote = getVote(voteId); checkIfVotingEnabled(vote); checkIfUpdateConditionsAreConsistent(vote); @@ -69,10 +69,10 @@ public CastVote castVote( CastVote receipt; if (vote.getParameters().canUpdate) { - receipt = vote.addCastVote(getWsUserName(), theVote); - } else { + final String proxyId = getWsUserName(); + receipt = vote.addCastVote(proxyId, theVote, getAssurances()); + } else receipt = vote.addCastVote(null, theVote); - } vote.removeBallot(ballot); return receipt; @@ -80,119 +80,106 @@ public CastVote castVote( private void validatePreferences(final List theVote, final Vote vote) { - for (RankedChoice choice : theVote) { + for (final RankedChoice choice : theVote) validateOnePreference(vote, choice); - } } private void validateOnePreference(final Vote vote, final RankedChoice choice) { - if (!vote.getChoices().containsKey(choice.choiceId)) { + if (!vote.getChoices().containsKey(choice.choiceId)) throw new ReportedException("Invalid choiceId"); - } - if (choice.rank < 0) { + if (choice.rank < 0) throw new ReportedException("Invalid rank"); - } } private void validateBallot(final String ballot, final Vote vote) { - if (!vote.getBallots().contains(ballot)) { + if (!vote.getBallots().contains(ballot)) throw new ReportedException("Illegal ballot"); - } } private void checkIfUpdateConditionsAreConsistent(final Vote vote) { if ( vote.getParameters().canUpdate && getWsContext().getUserPrincipal() == null - ) { + ) throw new ReportedException( "canUpdate is true but the user is not authenticated" ); - } } private void checkIfVotingEnabled(final Vote vote) { - if (!vote.parameters.canVote) { + if (!vote.parameters.canVote) throw new ReportedException("This issue cannot be voted on yet"); - } } @Override public void modifyVote(final VoteAdminInfo voteAdminInfo, final String voteName) { ValidationUtil.checkVoteName(voteName); - Vote vote = checkIfVoteCanBeModified(voteAdminInfo); + final Vote vote = checkIfVoteCanBeModified(voteAdminInfo); vote.name = voteName; } @Override public void deleteVote(final VoteAdminInfo adminInfo) { - Vote vote = checkIfVoteCanBeModified(adminInfo); + final Vote vote = checkIfVoteCanBeModified(adminInfo); session.remove(vote); } private Vote checkIfVoteCanBeModified(final VoteAdminInfo adminInfo) { - Vote vote = checkAdminInfo(adminInfo); + final Vote vote = checkAdminInfo(adminInfo); - if (vote.hasIssuedBallots()) { + if (vote.hasIssuedBallots()) throw new IllegalArgumentException( "This vote cannot be modified it has issued ballots." ); - } return vote; } private Vote checkAdminInfo(final VoteAdminInfo adminInfo) { - Vote vote = getVote(adminInfo.voteId); + final Vote vote = getVote(adminInfo.voteId); vote.checkAdminKey(adminInfo.adminKey); return vote; } @Override public JsonObject showVote(final VoteAdminInfo adminInfo) { - Vote vote = checkAdminInfo(adminInfo); - if (!adminInfo.adminKey.equals(vote.adminKey)) { + final Vote vote = checkAdminInfo(adminInfo); + if (!adminInfo.adminKey.equals(vote.adminKey)) checkAssurances(vote); - } return vote.toJson(); } private void checkAssurances(final Vote vote) { - for (String assurance : vote.countedAssurances) { - if (!this.hasAssurance(assurance)) { + for (final String assurance : vote.countedAssurances) + if (!hasAssurance(assurance)) throw new ReportedException("missing assurances", assurance); - } - } } @Override public String deleteChoice(final VoteAdminInfo voteAdminInfo, final String choiceId) { - Vote vote = + final Vote vote = getVoteIfModifiable(voteAdminInfo.voteId, voteAdminInfo.adminKey); - Choice votesChoice = vote.getChoice(choiceId); + final Choice votesChoice = vote.getChoice(choiceId); if ("user".equals(voteAdminInfo.adminKey)) { if (votesChoice.userName.equals(getWsUserName())) { - if (vote.parameters.canAddin) { + if (vote.parameters.canAddin) vote.choices.remove(votesChoice.id); - } else { + else throw new IllegalArgumentException( "The adminKey is \"user\" but canAddin is false." ); - } - } else { + } else throw new IllegalArgumentException( "The adminKey is \"user\" but the user is not same with that user who added the choice." ); - } - } else { + } else vote.choices.remove(votesChoice.id); - } return "OK"; } @@ -201,23 +188,21 @@ public void modifyChoice( final VoteAdminInfo adminInfo, final String choiceId, final String choiceName ) { - Vote vote = getVoteIfModifiable(adminInfo.voteId, adminInfo.adminKey); + final Vote vote = getVoteIfModifiable(adminInfo.voteId, adminInfo.adminKey); - Choice votesChoice = vote.getChoice(choiceId); + final Choice votesChoice = vote.getChoice(choiceId); if ("user".equals(adminInfo.adminKey)) { - if (!vote.parameters.canAddin) { + if (!vote.parameters.canAddin) throw new ReportedException( "Choice modification disallowed: adminKey is user, but canAddin is false" ); - } - if (!votesChoice.userName.equals(getWsUserName())) { + if (!votesChoice.userName.equals(getWsUserName())) throw new ReportedException( "Choice modification disallowed: adminKey is user, " + "and the choice was added by a different user", votesChoice.userName ); - } } votesChoice.name = choiceName; @@ -227,19 +212,25 @@ public void modifyChoice( public void setVoteParameters( final VoteAdminInfo adminInfo, final VoteParameters voteParameters ) { - Vote vote = checkAdminInfo(adminInfo); + final Vote vote = checkAdminInfo(adminInfo); - if (voteParameters.minEndorsements >= 0) { + if (voteParameters.minEndorsements >= 0) vote.setParameters( voteParameters.minEndorsements, voteParameters.canAddin, voteParameters.canEndorse, voteParameters.canVote, voteParameters.canView ); - } else { + else throw new ReportedException( "Illegal minEndorsements", Integer.toString(voteParameters.minEndorsements) ); - } } + + @Override + public List getAssurances() { + final String wsUserName = getWsUserName(); + return assuranceManager.getAssurances(wsUserName); + } + } diff --git a/src/main/java/org/rulez/demokracia/pdengine/Voteable.java b/src/main/java/org/rulez/demokracia/pdengine/Voteable.java index 052d8103..46262340 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/Voteable.java +++ b/src/main/java/org/rulez/demokracia/pdengine/Voteable.java @@ -7,15 +7,24 @@ public interface Voteable extends VoteInterface { default CastVote addCastVote(final String proxyId, final List theVote) { + final CastVote castVote = new CastVote(proxyId, theVote); + getVotesCast().add(castVote); + return castVote; + } + + default CastVote addCastVote( + final String proxyId, final List theVote, + final List assurances + ) { final Iterator listIterator = getVotesCast().iterator(); while (listIterator.hasNext()) { final CastVote element = listIterator.next(); - if (element.proxyId != null && element.proxyId.equals(proxyId)) + if (element.proxyId.equals(proxyId)) listIterator.remove(); } - final CastVote castVote = new CastVote(proxyId, theVote); + final CastVote castVote = new CastVote(proxyId, theVote, assurances); getVotesCast().add(castVote); castVote.updateSignature(); return castVote; diff --git a/src/main/java/org/rulez/demokracia/pdengine/dataobjects/CastVoteEntity.java b/src/main/java/org/rulez/demokracia/pdengine/dataobjects/CastVoteEntity.java index 3e88c9dd..398fbf0e 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/dataobjects/CastVoteEntity.java +++ b/src/main/java/org/rulez/demokracia/pdengine/dataobjects/CastVoteEntity.java @@ -14,6 +14,7 @@ public class CastVoteEntity extends BaseEntity { public List preferences; public String proxyId; public String secretId; + public List assurances; public String signature; } diff --git a/src/main/java/org/rulez/demokracia/pdengine/servlet/VoteManagerInterface.java b/src/main/java/org/rulez/demokracia/pdengine/servlet/VoteManagerInterface.java index 0806c142..65c3f85c 100644 --- a/src/main/java/org/rulez/demokracia/pdengine/servlet/VoteManagerInterface.java +++ b/src/main/java/org/rulez/demokracia/pdengine/servlet/VoteManagerInterface.java @@ -40,25 +40,27 @@ public class VoteManagerInterface { public Response createVote(final CreateVoteRequest request) { VoteAdminInfo adminInfo; try { - adminInfo = IVoteManager.getVoteManager(wsContext).createVote( + adminInfo = IVoteManager.getVoteManager( + wsContext, IVoteManager.getAssuranceManager() + ).createVote( request.voteName, request.neededAssurances, request.countedAssurances, request.isPrivate, request.minEndorsements ); - } catch (ReportedException e) { - JsonObject jsonObject = new JsonObject(); + } catch (final ReportedException e) { + final JsonObject jsonObject = new JsonObject(); jsonObject.add("error", e.toJSON()); jsonObject.add("input", new Gson().toJsonTree(request)); - String result = new Gson().toJson(jsonObject); + final String result = new Gson().toJson(jsonObject); LOGGER.log(Level.FINE, result); return Response.status(400).entity(result).build(); } - JsonObject jsonObject = new JsonObject(); + final JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("adminKey", adminInfo.adminKey); jsonObject.addProperty("voteId", adminInfo.voteId); - String result = new Gson().toJson(jsonObject); + final String result = new Gson().toJson(jsonObject); return Response.status(200).entity(result).build(); } } diff --git a/src/test/java/org/rulez/demokracia/pdengine/CastVoteTest.java b/src/test/java/org/rulez/demokracia/pdengine/CastVoteTest.java index 9c46c760..28702391 100644 --- a/src/test/java/org/rulez/demokracia/pdengine/CastVoteTest.java +++ b/src/test/java/org/rulez/demokracia/pdengine/CastVoteTest.java @@ -1,6 +1,7 @@ package org.rulez.demokracia.pdengine; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; @@ -12,35 +13,55 @@ import org.rulez.demokracia.pdengine.annotations.TestedOperation; import org.rulez.demokracia.pdengine.testhelpers.CreatedDefaultChoice; +@TestedFeature("Supporting functionality") +@TestedOperation("CastVote") public class CastVoteTest extends CreatedDefaultChoice { @Override @Before public void setUp() { super.setUp(); + initializeVoteCastTest(); } - @TestedFeature("Supporting functionality") - @TestedOperation("CastVote") @TestedBehaviour("The preferences described by a cast vote can be obtained") @Test public void the_preferences_can_be_obtained_when_they_are_empty() { - List theCastVote = new ArrayList<>(); - CastVote castVote = new CastVote(TEST_USER_NAME, theCastVote); - List preferences = castVote.getPreferences(); + final CastVote castVote = new CastVote(TEST_USER_NAME, theCastVote); + final List preferences = castVote.getPreferences(); assertEquals(new ArrayList<>(), preferences); } - @TestedFeature("Supporting functionality") - @TestedOperation("CastVote") @TestedBehaviour("The preferences described by a cast vote can be obtained") @Test public void the_preferences_can_be_obtained_when_they_contain_choices() { - List theCastVote = new ArrayList<>(); theCastVote.add(new RankedChoice("1", 1)); - CastVote castVote = new CastVote(TEST_USER_NAME, theCastVote); - List preferences = castVote.getPreferences(); + final CastVote castVote = new CastVote(TEST_USER_NAME, theCastVote); + final List preferences = castVote.getPreferences(); assertEquals(theCastVote, preferences); } + @TestedBehaviour( + "The assurances of the voter can be obtained from a cast vote if canupdateis true" + ) + @Test + public void + the_assurances_of_the_voter_can_be_obtained_from_a_cast_vote_if_canupdate_is_true() { + vote.parameters.canUpdate = true; + final CastVote castVote = + voteManager.castVote(adminInfo.voteId, ballot, theCastVote); + assertEquals("magyar", castVote.assurances.get(0)); + } + + @TestedBehaviour( + "The assurances of the voter can be obtained from a cast vote if canupdateis true" + ) + @Test + public void the_assurances_of_the_voter_is_null_if_canupdate_is_false() { + vote.parameters.canUpdate = false; + final CastVote castVote = + voteManager.castVote(adminInfo.voteId, ballot, theCastVote); + final List assurances = castVote.getAssurances(); + assertTrue(assurances == null); + } } diff --git a/src/test/java/org/rulez/demokracia/pdengine/SessionTest.java b/src/test/java/org/rulez/demokracia/pdengine/SessionTest.java index e6ed3c1a..36dfbe62 100644 --- a/src/test/java/org/rulez/demokracia/pdengine/SessionTest.java +++ b/src/test/java/org/rulez/demokracia/pdengine/SessionTest.java @@ -48,8 +48,10 @@ public void user_assurances_are_checkable_from_the_voteManager() { @Test public void two_voteManagers_for_the_same_session_context_are_the_same() { final WebServiceContext wsContext = mock(WebServiceContext.class); - final IVoteManager voteManager1 = IVoteManager.getVoteManager(wsContext); - final IVoteManager voteManager2 = IVoteManager.getVoteManager(wsContext); + final IVoteManager voteManager1 = + IVoteManager.getVoteManager(wsContext, fakeAssuranceManager); + final IVoteManager voteManager2 = + IVoteManager.getVoteManager(wsContext, fakeAssuranceManager); assertEquals(voteManager1, voteManager2); } diff --git a/src/test/java/org/rulez/demokracia/pdengine/UnimplementedTests.java b/src/test/java/org/rulez/demokracia/pdengine/UnimplementedTests.java index 38e55558..08bd4194 100644 --- a/src/test/java/org/rulez/demokracia/pdengine/UnimplementedTests.java +++ b/src/test/java/org/rulez/demokracia/pdengine/UnimplementedTests.java @@ -1,7 +1,5 @@ package org.rulez.demokracia.pdengine; -import java.util.ArrayList; - import org.junit.Test; import org.rulez.demokracia.pdengine.annotations.TestedBehaviour; import org.rulez.demokracia.pdengine.annotations.TestedFeature; @@ -14,9 +12,8 @@ public class UnimplementedTests extends ThrowableTester { @Test - public void the_getAssurances_method_is_not_implemented_yet() { - assertUnimplemented( - () -> new CastVote("proxyId", new ArrayList<>()).getAssurances() - ); + public void getAssurances_in_ADAAssuranceManager_is_unimplemented() { + final ADAAssuranceManager a = new ADAAssuranceManager(); + assertUnimplemented(() -> a.getAssurances("UnImplementedTest")); } } diff --git a/src/test/java/org/rulez/demokracia/pdengine/testhelpers/CreatedDefaultVoteRegistry.java b/src/test/java/org/rulez/demokracia/pdengine/testhelpers/CreatedDefaultVoteRegistry.java index 662f9b62..ffe2c8c1 100644 --- a/src/test/java/org/rulez/demokracia/pdengine/testhelpers/CreatedDefaultVoteRegistry.java +++ b/src/test/java/org/rulez/demokracia/pdengine/testhelpers/CreatedDefaultVoteRegistry.java @@ -12,6 +12,7 @@ import org.junit.Before; import org.mockito.MockitoAnnotations; +import org.rulez.demokracia.pdengine.AssuranceManager; import org.rulez.demokracia.pdengine.IVoteManager; import org.rulez.demokracia.pdengine.Vote; import org.rulez.demokracia.pdengine.dataobjects.VoteAdminInfo; @@ -29,11 +30,15 @@ public class CreatedDefaultVoteRegistry extends ThrowableTester { protected Set countedAssurances; protected boolean isPrivate; protected int minEndorsements; + protected AssuranceManager fakeAssuranceManager; @Before public void setUp() { final WebServiceContext wsContext = setupMockWsContext(); - voteManager = IVoteManager.getVoteManager(wsContext); + fakeAssuranceManager = mock(AssuranceManager.class); + when(fakeAssuranceManager.getAssurances(TEST_USER_NAME)) + .thenReturn(Arrays.asList("magyar", "német")); + voteManager = IVoteManager.getVoteManager(wsContext, fakeAssuranceManager); neededAssurances = new HashSet<>(); countedAssurances = new HashSet<>(); isPrivate = true; @@ -64,7 +69,7 @@ private WebServiceContext setupMockWsContext() { public void setupUnauthenticatedMockWsContext() { final WebServiceContext wsContext = mock(WebServiceContext.class); when(wsContext.getUserPrincipal()).thenReturn(null); - voteManager = IVoteManager.getVoteManager(wsContext); + voteManager = IVoteManager.getVoteManager(wsContext, fakeAssuranceManager); } protected VoteAdminInfo createAVote() {