Giter Club home page Giter Club logo

cocorico's People

Contributors

franklinovitch avatar jmlx42 avatar virgile-dev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cocorico's Issues

Whitelist Safari

Thanks to #64 the app should now work on Safari.
If that's the case, Safari (macOS and iOS) should be added to the Web browser whitelist.

Implement a ballot audit procedure

When we have #43, the /vote/ballot-box page should provide a way to "audit" one's ballot.

To audit its ballot, the user will have to provide (scan or select the file) his "proof of vote". From this proof of vote, we can read:

  • the vote ID
  • the blockchain account address
  • the ballot value / voted proposal

We can then make sure that triplet matches with an actual ballot transaction/event on the blockchain and show a side-by-side comparison of the proof of vote and the blockchain data.

Every time a user audits his ballot, we should increment a counter to know how many audits have succeeded/failed. On the ballot box page, we could then show:

  • the %age of audited ballot
  • the %age of successfully verified ballots
  • add a button to scan the proof of vote
  • add a button to select the proof of vote file
  • implement the /ballot/verify API endpoint
  • log and display the ballot audit success rate

Webhooks

3rd party Apps - especially if they provide there own user database - are more than likely to need to know what voter participated to what vote. For example, LaPrimaire.org must be able to send reminders to the people who did not complete the voting process.

One could use blockchain events or we could provide a way for our smart contract to call a specified sub-contract. But the blockchain stores only the ballot values and has no information about the "real" user. This method cannot apply here but could be used for monitoring the voting process itself instead of the state of the users.

Thus, 3rd party Apps integrating Cocorico should be made aware of vote/ballot events using webhooks.
When registering an App, the developer should be able to provide web hooks for the following events (at least):

  • a ballot has been successfully recorded on the blockchain
  • an error happened while trying to record a ballot
  • automatically retry failed (non 2XX) webhook calls
  • send an e-mail when a webhook call failed for more than 1 day

Those webhooks must guarantee the privacy of the user and avoid sending private data. For example, the webhook can tell you that the user has successfully voted, but will not give you the value on the ballot.

Still, even if the webhooks does not tell the 3rd party App what the user voted, it still weakens the privacy model of Cocorico since even the information about who did (not) vote is not kept/made available in the platform itself as of today.

Another concern with webhooks is how unpredictable they are:

  • a webhook could return a massive amount of data in order to crash/stall Cocorico
  • a webhook could be unavailable when it is called by the platform
  • any faulty webhook call could crash the corresponding requesting process and might prevent ballots to be fully processed
  • we need to make sure the server behind the webhook is legit ("IP addresses can be spoofed, and DNS can be compromised, but fortunately we have cryptographic tools")

Webhooks best practices:

Implementation ideas:

  • webhook data should be a JWT signed with the destination App secret
  • each webhook data should have a unique ID
  • accept only HTTPS webhooks URIs
  • webhook calls should be stored in a persistent queue and retried as long as they don't respond with 2XX
  • webhook response should have a timeout (max 10sec for example)
  • webhook queue handling should be a separate process

Too many ports exposed to remote connections

The voting machine is composed of many software parts. Some of them listen to one or many ports on both the loopback network interface and other public-facing interfaces. Although the security of the voting mecanism shouldn't rely on preventing access to the machine itself, it is still a good idea to lower the attack surface.

Here is a list of all processes listening to TCP or UDP ports.

root@local:~# netstat -pluton
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name Timer
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      706/rpcbind      off (0.00/0/0)
tcp        0      0 0.0.0.0:28017           0.0.0.0:*               LISTEN      1128/mongod      off (0.00/0/0)
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1764/sshd        off (0.00/0/0)
tcp        0      0 0.0.0.0:15672           0.0.0.0:*               LISTEN      1041/beam.smp    off (0.00/0/0)
tcp        0      0 0.0.0.0:55672           0.0.0.0:*               LISTEN      1041/beam.smp    off (0.00/0/0)
tcp        0      0 127.0.0.1:8545          0.0.0.0:*               LISTEN      1834/geth        off (0.00/0/0)
tcp        0      0 0.0.0.0:46307           0.0.0.0:*               LISTEN      754/rpc.statd    off (0.00/0/0)
tcp        0      0 0.0.0.0:49414           0.0.0.0:*               LISTEN      1041/beam.smp    off (0.00/0/0)
tcp        0      0 0.0.0.0:27017           0.0.0.0:*               LISTEN      1128/mongod      off (0.00/0/0)
tcp        0      0 127.0.0.1:6379          0.0.0.0:*               LISTEN      1243/redis-server 1 off (0.00/0/0)
tcp6       0      0 :::111                  :::*                    LISTEN      706/rpcbind      off (0.00/0/0)
tcp6       0      0 :::80                   :::*                    LISTEN      1378/apache2     off (0.00/0/0)
tcp6       0      0 :::4369                 :::*                    LISTEN      1077/epmd        off (0.00/0/0)
tcp6       0      0 :::22                   :::*                    LISTEN      1764/sshd        off (0.00/0/0)
tcp6       0      0 :::40886                :::*                    LISTEN      754/rpc.statd    off (0.00/0/0)
tcp6       0      0 :::3000                 :::*                    LISTEN      2286/nodejs      off (0.00/0/0)
tcp6       0      0 :::443                  :::*                    LISTEN      1378/apache2     off (0.00/0/0)
tcp6       0      0 :::30303                :::*                    LISTEN      1834/geth        off (0.00/0/0)
tcp6       0      0 :::5672                 :::*                    LISTEN      1041/beam.smp    off (0.00/0/0)
udp        0      0 0.0.0.0:10841           0.0.0.0:*                           635/dhclient     off (0.00/0/0)
udp        0      0 0.0.0.0:873             0.0.0.0:*                           706/rpcbind      off (0.00/0/0)
udp        0      0 127.0.0.1:930           0.0.0.0:*                           754/rpc.statd    off (0.00/0/0)
udp        0      0 0.0.0.0:40331           0.0.0.0:*                           754/rpc.statd    off (0.00/0/0)
udp        0      0 0.0.0.0:68              0.0.0.0:*                           635/dhclient     off (0.00/0/0)
udp        0      0 0.0.0.0:111             0.0.0.0:*                           706/rpcbind      off (0.00/0/0)
udp6       0      0 :::873                  :::*                                706/rpcbind      off (0.00/0/0)
udp6       0      0 :::50384                :::*                                754/rpc.statd    off (0.00/0/0)
udp6       0      0 :::26304                :::*                                635/dhclient     off (0.00/0/0)
udp6       0      0 :::111                  :::*                                706/rpcbind      off (0.00/0/0)

Here is a list of TCP ports open to connection from outside the voting machine.

$ nmap 192.168.50.42 -p-

Starting Nmap 7.12 ( https://nmap.org ) at 2016-10-15 17:58 CEST
Nmap scan report for local.cocorico.cc (192.168.50.42)
Host is up (0.00036s latency).
Not shown: 65521 closed ports
PORT      STATE SERVICE
22/tcp    open  ssh
80/tcp    open  http
111/tcp   open  rpcbind
443/tcp   open  https
3000/tcp  open  ppp
4369/tcp  open  epmd
5672/tcp  open  amqp
15672/tcp open  unknown
27017/tcp open  mongod
28017/tcp open  mongod
30303/tcp open  unknown
46307/tcp open  unknown
49414/tcp open  unknown
55672/tcp open  unknown

Nmap done: 1 IP address (1 host up) scanned in 2.65 seconds

In order to lower the number of ports exposed to the public, we should:

  • Shut down any software that is not absolutely required (eg. Redis);
  • Configure softwares so that they listen on the minimum number of interfaces and ports (eg. Mongodb, RabbitMQ);
  • Add a firewall (eg. iptables) to allow remote connections to whitelisted ports only.

LaPrimaire.org vote label typo

There is a typo in one of the vote labels which is written "tres bien" instead of "très bien".

Edit : translated from French from the original message below

Il manque un accent grave au vote "tres bien", qui devrait être écrit "très bien".

Fork blockchain workers

The blockchain (vote & ballot) workers run as single processes.
We should use NodeJS cluster feature to fork them and handle each queue with multiple consumers.

geth accept error

I1105 16:25:30.644935 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:31.660103 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:32.694325 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:33.697415 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:34.708284 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:35.766081 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:36.767862 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:37.779899 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:38.819855 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s

It might be related to the ballot consumer not properly removing filters.
It would be better to create a separate new web3 instance in each relevant ballot step and to reset() it when the step is done.

Add a way to localize pages

This should be done AFTER #27.

Pages are stored in the database and can be edited through the CMS admin.
For now, pages are 100% French content, including their content but also their slug.

Pages are loaded by the Web app by the Page component using the page slug. Example:

<Page slug="accueil"/>

The easiest way to proceed would be to rely on react-intl to localize the page slugs.

First, we create a copy of each page and translate it into another locale (English?).

Second, we add a "page" section to the intl.js file:

page : {
  HOME: "accueil",
  HELP: "aide",
  // all the other slugs...
}

Third, we change all references to the Page component to read the slug from the locale using getIntlMessage(). Example :

<Page slug="accueil"/>

becomes:

<Page slug={this.getIntlMessage('page.HOME'}/>

Here is the todo list:

  • localize all existing pages in English
  • update the intl.js file with a "page" section
  • replace all hardcoded slugs by calls to getIntlMessage() when using the Page component

Spanish translation for "Politique de Confidentialité"

The "Política de privacidad" page is just a placeholder:

https://github.com/promethe42/cocorico/blob/master/api/db/pages/privacy-policy.html

We need to fix it by translating/adapting the content of:

https://github.com/promethe42/cocorico/blob/master/api/db/pages/politica-de-privacidad.md

Documentation about how to translate pages is here:

https://github.com/promethe42/cocorico/blob/master/doc/Localization.md#translating-pages

Does it make sense to keep the FranceConnect stuff in the Spanish version?
Should we go for a more generic "digital ID" thing?

Continuous integration

Continuous integration using Travis CI:

  • run unit tests on PRs #41
  • run eslint on PRs to validate the coding style
  • automated production deployment

Optimized initial user account balance

Today, the root "authority" blockchain accounts credits the user browser-side generated account with more than enough ETH to perform the smart contract method call.
We should credit only the minimum amount of ETH necessary to handle the call transaction.

With this modification, the balance of the user account should be 0.
If it's not zero, the balance should be sent back to the root account.

Webhooks are called one after the other

Currently, webhooks are called synchronously. This is because we process webhook messages from RabbitMQ one by one through a single channel (a RabbitMQ channel is synchronous by nature).

Potential solutions are:

  • consume multiple messages at the same time and acknowledge them when associated webhook is successfully called (this might imply switching to the "promise" paradigme);
  • communicate with RabbitMQ through multiple channels in parallel ;
  • start multiple instances of the webhook worker (pm2 might be helpful here).

English translation for "Politique de Confidentialité"

The "Privacy Policy" page is just a placeholder:

https://github.com/promethe42/cocorico/blob/master/api/db/pages/privacy-policy.html

We need to fix it by translating/adapting the content of:

https://github.com/promethe42/cocorico/blob/master/api/db/pages/politique-de-confidentialite.md

Documentation about how to translate pages is here:

https://github.com/promethe42/cocorico/blob/master/doc/Localization.md#translating-pages

Does it make sense to keep the FranceConnect stuff in the English version?
Should we go for a more generic "digital ID" thing?

Leverage advanced RabbitMQ features to implement cheap webhook retry mechanism

Currently, webhook messages whose HTTP call fails are consumed and requeued from/to RabbitMQ continuously. Doing so wastes a full CPU core for nothing. A less costly approach would be to use the dead-letter mechanism RabbitMQ provides.

Here is the general idea:

  1. After each ballot, a webhook message is enqueued into the webhook queue.
  2. The webhook worker consumes these messages in order and tries to call the associated remote server.
  3. It the call fails, the worker rejects the webhook message.
  4. Rejected messages are automatically routed to an isolation queue with no consumer.
  5. After a certain amount of time, isolated messages are automatically sent back to the webhook queue.
  6. The message can be rejected and delayed this way many times.
  7. When the webhook call succeeds, the worker acknowledges the message. Done.
  8. If the message becomes too old, the worker can silently acknowledge it to make it disappear from the queue.

This mechanism requires subtle configuration that I will describe here once I manage to have working POC.

Providing a "proof of vote"

The current voting process is cumbersome: we generate a complicated "vote card" which the user don't actually need. 99% of the data in that vote card is useless: the public key (or the address) alone would be enough as of now.

Yet, we offer no simple way to audit a ballot using the "vote card": we have the address of the account, but we have no idea about what the user actually voted. So it would be up to him to remember what he voted when he's going to audit his ballot in the ballot box.

We must keep generating the "vote card" since it's mandatory (it's basically the blockchain account used to create and sign the ballot transaction). Yet we could do all of it in the background and never tell the user about it.

Instead, we should create a new kind of token that can be used to assess/audit the ballot and its value in the ballot box. This would be a "proof of vote". This proof of vote would be a JWT containing:

  • version: a version number for backward compatibility
  • vote: the ID of vote
  • address: the address of the blockchain account that signed the ballot transaction
  • value: the actual ballot value

This JWT would be created and signed by the server as a response to the POST /api/ballot API endpoint. This JWT signing key should be unique per-vote and never made available by the API.

  • add a signing key to the Vote model
  • return the "proof of vote" JWT as a response to the POST /api/ballot API endpoint
  • add a button to download/print the proof of vote on the "complete" step of the VoteWidget

Make the voting proof QR Code an url so that the user can verify his vote more easily

Today, to verify your vote, you have to go to the ballot box page and upload your voting proof, a QR code that hides a JWT. It would be neat if the QR code would be a url with the JWT already appended to it so that, by scanning the QR code, the user would automatically come to a page that verifies its vote. This page would be different than the ballot box page so that one could verify his vote even if the voting process is not over yet.

Move non-page content into the locale files

Lots of messages are stored as pages in the database instead of a locale message. For example, the vote widget wording is mostly loaded from pages.

This is not cool because someone who wants to translate the app will have a hard time figuring what is where.

I did this originally because I wasn't sure I could properly format this kind of content in the locale file. But it turns out it's possible using <FormattedHTMLMessage> instead of the simpler <FormattedMessage>.

We should:

  • remove all the pages that are not actually being used by the app
  • move all the remaining non-page content into the locale file

New domain name

Hi there!

We can buy *.vote domains and they are not too expensive (<70€/year)!
We could buy the cocorico.vote domain for example.

But we could also see this as an opportunity to find a better brand.

Any suggestions?

How do I translate cocorico ?

Hey,

As discussed during the hackathon last week-end :

It'd be great to make cocorico available in other languages. How do you suggest we do that? Could you provide the link to the files that need translations?

Thanks!

API tests cannot run without connectivity

Currently, we use some URLs coming from meetup.com to run the API tests.
As a result, some tests will fail when there is no internet connectivity.

We should solve this by running a test-dedicated Web server with static content.

iframe postMessage data should include the value of the vote id

I use several cocorico iframe on one page. Each of these iframe emit messages with postMessage but I am unable to trace back which iFrame emitted which message if the message does not include the id of the vote (1 vote <-> 1 iframe). Unless I am mistaken, I did not see the id of the vote in the voteComplete nor voteSuccess MessageEvents.

image

My first idea would be to pass voteComplete_[voteId] as data but I am definitely not a JS expert :)

Transaction search

During the ODN4 hackathon, we've added an API endpoint and the corresponding page to list all the ballot blockchain transactions for a specific vote.

The goal of this page if to provide an easy way for anyone to explorer the content of the "digital ballot box" that is our smart contract.

First, we should add a "search by address" field. By entering (part of) its address (/public key), the user should be able to filter the transaction list to get only the matching ones. The existing /vote/transactions/:voteId API endpoint should be updated to support an optional "address" POST parameter and filter the transaction list to return only the one with an address that starts with the specified one.

Then, because typing an address is cumbersome and it is supposed to be embedded in the downloadable SVG vote card, we should provide a way for the user to provide his vote card instead of filling up the address form manually.

  • search transaction by address
  • search transaction by vote card

ATTENTION! For privacy reasons, the vote card must NOT be sent to the server at any time. We already have existing Web app code to ask the user to provide his vote card without sending anything to the server and this code should be re-used.

Allow the UI locale to be specified (forced) at vote creation

Today the locale in which the text is displayed is being automatically selected depending on the user's browser locale configuration. Given that (i) labels and messages are not localized and (ii) multi-language voting is very likely a rare case (by default english will be used), it would be good to be able to force the use of a specific locale at vote creation time (/api/vote). I would add 'locale' as an optional parameter.

Queue consumers do not reconnect when queue broker is restarted

The vote, ballot and webhook workers all connect to RabbitMQ at startup. However, when RabbitMQ is restarted, they do not reconnect by themselves. To have them continue consuming messages from the broker, they have to be restarted intentionally.

I can think of at least two potential solutions to this problem:

  1. Automatically restart the 3 workers when RabbitMQ is restarted — provided message processing is reentrant (which, if it is not the case, is another kind of problem).
  2. Have the 3 workers reconnect by themselves when the connection to RabbitMQ is lost. Such code should be shared between workers (as a base class, for example).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.