Welcome to the BlockPower Voting Ambassador Platform project! BlockPower is a nonprofit focused on increasing voter turnout among Black citizens who don't vote regularly. BlockPower pays people in majority-Black neighborhoods to be "Voting Ambassadors" and talk with their friends, family members, and neighbors about the importance of voting. A Voting Ambassadors asks these friends, family members and neighbors to become "Vote Triplers" who will, in turn, remind 3 other people in their community to vote. This software platform enables Voting Ambassadors to find people they know in the database, text them through the platform about their commitment to be a Vote Tripler and remind 3 others to vote, and to receive payments for affirmative responses from their Vote Triplers.
A sign-up form followed by a training module leads to the dashboard, where a Voting Ambassador can get started looking for people they know in the platform database. By default, the Voting Ambassador will be shown a list of people in their area (within a configurable number of meters from the Ambassador) with socially matched Vote Triplers at the top of the list if any exist for the Voting Ambassador. The geographic distance is calculated via the Neo4J apoc.distance function, using the Point data type either imported from CSV in the case of a Vote Tripler, or pulled from an external API (census.gov) in the case of Voting Ambassadors. Voting Ambassadors can also find people they know in the list by setting a variety of search filters, including first and last name, phone number, metro area, age, gender and geographic proximity. The Voting Ambassador can then "claim" a tripler by selecting one or more from the list. If a Vote Tripler is already claimed, no other Voting Ambassadors will see them in their lists going forward and therefore cannot claim an already claimed Vote Tripler.
Once the Ambassador has "claimed" one or more Vote Triplers, they can contact these Vote Triplers via standardized text (via a pool of Twilio longcodes) through the platform. The text will be sent to the Vote Tripler, prompting a confirmation that they will remind 3 others to vote. If that Vote Tripler responds "Yes" to the SMS, the system will record a pending payment for the Voting Ambassador. There is a configurable maximum number of Vote Triplers each Voting Ambassador can claim, and payment amount per confirmed Vote Tripler is also configurable. Voting Ambassadors can go through a simple process via Plaid-Link to login to their bank account and link it to the platform for payments via Stripe Connected Account or via PayPal for Voting Ambassadors pre-approved to use PayPal.
Also see the CONTRIBUTING document for more background and a technical overview.
A Vote Ambassador signs up with and interacts mainly with the React front-end. The front-end code can be found here: hello-voter.
This software also has the concept of "admin", an Ambassador account which is empowered to block Ambassadors, make another Ambassador an admin, and download CSV data reports of Ambassadors and their claimed Triplers.
The admin panel can be found here: https://github.com/colab-coop/HelloVoter-admin-ui.
- Node (we are using 12.18.2 in production). We recommend installing via Node Version Manager.
- Docker is required to get the database running.
- Copy
.env.example
to.env
and modify as needed:cp server/.env.example server/.env
- If you use nvm, run 'nvm use' to install the right version of node
- Install dependencies:
npm install
- Setup the database:
npm run database
- (optional) Seed the database with fake data:
(cd server && npm run seed:fresh)
- Start the server:
npm start
After following the steps above,
- The API will be available at http://localhost:8080/api/v1/
- The Neo4j Browser will be available at http://localhost:7474/browser/
- Username
neo4j
, default passwordhellovoter
- Example query to see all data:
MATCH (n) RETURN n
- Username
For local development without requiring real OAuth:
- Set
REACT_APP_NO_AUTH=1
- Modify an Ambassador to work with a mock Authorization token:
MATCH (a:Ambassador {admin: true}) SET a.external_id = "noauth:localuser"
- Use this Bearer token when making requests:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Im5vYXV0aDpsb2NhbHVzZXIiLCJuYW1lIjoiTG9jYWwgVXNlciIsImVtYWlsIjoibG9jYWxAbG9jYWxob3N0IiwiaXNzIjoib3Vydm9pY2V1c2Eub3JnIiwiaWF0IjoxLCJleHAiOjIsImRpc2NsYWltZXIiOiJCbGFoIGJsYWggZGlzY2xhaW1lciJ9.qa5K2pgi1uLYkV7jP3aNvazcchvgBD8RwhdG6Q86GxlvusQx7nNCTr3LrAnn6pxDJxNidJoqjD3Ie77jj5hWK_-lbgtHMLhNXGExDxI8pQ0I5ZnAV_5pDu7vARinoy3mctQWFO2pIQSu8KzQc7eQ90IQZBseE7nQV-ugZRfK8Teo_48COcJxGxqwCNCO80G_JzBoif2xaWRb2i2n0qeSUKfXN4Fwy46JOiHFnL9yOS5s54tB6doe1wFJNYps8eVQbVkTBL1I9PQP4Gs-BmzND0vcQaczTdu_J50uvLL5do1FHb48lRhrA44ZrYv3EVwNsJXZtH3MbasxgPrZhl69VQ
- See hellovoter.log for output:
less +F server/hellovoter.log
Note the deployment branch for the api is "ambassador", with tagged releases.
We (CoLab) are currently using an AWS cluster to deploy all of this code (api, frontend, and admin-ui). We use an Ansible playbook to provision the servers. We point the servers to a Neo4J database hosted at Graphene. The frontend is also hosted on an AWS server in the cluster, also using an Ansible playbook. We have CircleCI workflows implemented for deployment.
You are, of course, free to deploy in any way you wish, but we have not attempted any other deployment configuration so YMMV.
Software License Agreement (AGPLv3+)
Copyright (c) 2020, Our Voice USA. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Affero General Public License
as published by the Free Software Foundation; either version 3
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
NOTE: We relicense the mobile app code for the purposes of distribution on the App Store. For details, read our CLA Rationale
Logos, icons, and other artwork depicting the Our Voice bird are copyright and not for redistribution without express written permission by Our Voice USA.
The server requires a .env
file to exist in the /server directory. This file controls the configuration of the api.
The meaning of each config item is as follows:
SERVER_PORT
: Port for node to listen on for http requests.NEO4J_PROTOCOL
: Protocol for talking to neo4j.NEO4J_HOST
: Hostname of your neo4j server.NEO4J_PORT
: Port number of your neo4j server.NEO4J_USER
: Username to use to connect to neo4j.NEO4J_PASSWORD
: Password to use to connect to neo4j.NEO4J_ENTERPRISE
: Flag to enable enterprise features in neo4j.NEO4J_JMX_PORT
: The port on yourNEO4J_HOST
that exposes JMX. This port isn't exposed by default by Neo4j. See "Neo4j Configuration" below for how to set this up on the database side.NEO4J_JMX_USER
: Username to use to connect to neo4j jmx.NEO4J_JMX_PASS
: Password to use to connect to neo4j jmx.ENABLE_GEOCODE
: Allow import of data that doesn't have longitude/latitudeDISABLE_JMX
: Don't attempt to connect to neo4j jmx.DISABLE_APOC
: Don't use the neo4j apoc plugin. This limits data import functionality.DISABLE_SPATIAL
: Don't use the neo4j spatial plugin. This limit turf functionality.IP_HEADER
: Name of the header to check for, if you're behind an http reverse proxy and want to deny direct http requests.GOOGLE_MAPS_KEY
: API Key for Google maps. Get one here: https://developers.google.com/maps/documentation/javascript/get-api-keyJOB_CONCURRENCY
: Number of import jobs that can run in parallel. This is only relevant if you're using Neo4j Enterprise Edition, as Community Edition is limited to 4 CPUs, and the minimum CPUs required for parallel jobs is 6.SM_OAUTH_URL
: URL of the oauth provider.JWT_PUB_KEY
: Path to the public key of the oauth provider.WABASE
: URL of the HelloVoterHQ react application.AUTOENROLL_FORMID
: The ID of the form new volunteers get auto-enrolled in with autoturf set so they can go right into the map with data, no approval needed. We use this for our demo server. You probably don't want to set this.VOLUNTEER_ADD_NEW
: Whether or not volunteers can add new addresses & people that don't exist in the database.PURGE_IMPORT_RECORDS
: By default, import records are kept in the database, so you can trace where things came from. For larger operations (>20 million), we recommend setting this to1
as otherwise the speed of data imports will be significantly impacted.DEBUG
: Whether or not cypher and other debugging info is sent to the console log.PAYOUT_STRIPE
: Whether or not stripe is supported as a payout method.PAYOUT_PAYPAL
: Whether or not paypal is supported as a payout method.PAYOUT_PER_TRIPLER
: Amount in cents to be disbursed to the ambassador for every confirmed tripler.PLAID_CLIENT_ID
: The client ID from your Plaid developer account. Needed for ambassador payouts.PLAID_SECRET
: The secret from your Plaid developer account. Needed for ambassador payouts.PLAID_PUBLIC_KEY
: The public key from your Plaid developer account. Needed for ambassador payouts.PLAID_ENVIRONMENT
: The environment plaid is running in, can be sandbox, development or production.STRIPE_SECRET_KEY
: The secret key from your Stripe developer account. Needed for ambassador payouts.PAYPAL_ENVIRONMENT
: The environment paypal is running in, can be sandbox, development or production.PAYPAL_CLIENT_ID
: The client ID from your Paypal developer account. Needed for ambassador payouts.PAYPAL_CLIENT_SECRET
: The secret key from your Paypal developer account. Needed for ambassador payouts.TWILIO_DISABLE
: Setting it to true will disable twilio.TWILIO_ACCOUNT_SID
: SID of twilio account.TWILIO_AUTH_TOKEN
: Auth token of twilio account.TWILIO_FROM
: Number to send SMSes from.TWILIO_SUPPORT_PROXY_RESPONSE
: Support proxy messages for development; message and proxy number separated by =>. For example: yes=>+1 111-111-1111ORGANIZATION_NAME
: The name of the orgAMBASSADOR_LANDING_PAGE
: Link to the webpage where ambassador lands after approval, this is sent in SMSBUSINESS_URL
: URL of the business running the platform or url of the organization; used in stripe while creating connect accountsAMBASSADOR_APPROVED_MESSAGE
: The SMS message when an ambassador is approvedAMBASSADOR_SIGNUP_MESSAGE
: The SMS message when an ambassador signs upTRIPLER_REMINDER_MESSAGE
: The SMS message when a tripler is remindedTRIPLER_CONFIRMATION_MESSAGE
: The SMS message when a tripler begins confirmation processTRIPLER_RECONFIRMATION_MESSAGE
: The SMS message when a tripler responds to other than YES or NO in response to confirmation messageLOG_REQUESTS
: If set to true, enable request/response body loggingLOG_REQUEST_MAX_BODY_LENGTH
: Maximum number of characters logged during request/response logging, default set to 1000MAKE_ADMIN_API
: Flag to enablePUT /admin
api which makes an ambassador amin, default set to falseAMBASSADOR_TRIPLER_RELATION_MAX_DISTANCE
: Distance in meters to decide if a tripler can be suggested to ambassador, default set to 10000SUGGEST_TRIPLER_LIMIT
: Maximum number of triplers returned by suggest-triplers api, default set to 1000CLAIM_TRIPLER_LIMIT
: Maximum number of triplers an ambassador can claim (unless overridden by the claim_tripler_limit property on the ambassador), default set to 12PAYOUT_SCHEDULE
: Payout schedule in minutes, default set to 60 minutesFIFO_WAKEUP
: FIFO queue wakeup/sleep interval in milliseconds, default set to 300 msecDISABLE_AUTO_PAYOUTS
: Disable automatic payoutsDISABLE_JMX
: Disable JMX check from startupDISABLE_EMAILS
: Disable email notificationsSMTP_SERVICE
: Name of the SMTP service being usedSMTP_FROM
: Email from which emails are to be sentSMTP_USER
: User name for authorizing with SMTP serverSMTP_PASSWORD
: Password for authorizing with SMTP serverSMTP_SERVER
: Address of SMTP serverSMTP_USE_TLS
: Set to true if SMTP server supports secure connectionsSMTP_PORT
: Port at which SMTP server is listening for connectionsADMIN_EMAILS
: Comma separated list of admin emailsNEW_AMBASSADOR_SIGNUP_ADMIN_EMAIL_SUBJECT
: Subject of the email sent to admins when new ambassador signs upNEW_AMBASSADOR_SIGNUP_ADMIN_EMAIL_BODY
: Body of the email sent to admins when new ambassador signs upTRIPLER_CONFIRM_ADMIN_EMAIL_SUBJECT
: Subject of the email sent to admins when a tripler confirmsTRIPLER_CONFIRM_ADMIN_EMAIL_BODY
: Body of the email sent to admins when a tripler confirmsDISABLE_UPGRADE_SMS
: Flag to disable the tripler upgrade sms background jobUPGRADE_SMS_WAITING_PERIOD
: The time interval (in minutes)UPGRADE_SMS_SCHEDULE
: The time interval (in minutes) where the tripler upgrade sms background job firesTRIPLER_UPGRADE_MESSAGE
: The SMS message when a tripler responds YES, informing them that they are eligible to become Voter AmbassadorsWORDPRESS_LANDING
: The URL for the landing page for when a Tripler wants to upgrade to AmbassadorALLOWED_STATES
: A comma-separated list of 2-letter US state codes that determine which addresses are valid for ambassador signupsTRIPLER_CONFIRMED_AMBASSADOR_NOTIFICATION
: The SMS message that gets sent to the ambassador when one of their triplers is confirmed.BLOCKED_CARRIERS
: A pipe-delimited list of carrier strings in order to block fraudulent phone numbers.EKATA_API_KEY
: API key used for reverse phone lookup API from Ekata.com.EKATA_ADDON
: If Ekata is available as a Twilio add-on, set this to true.REJECTION_SMS_FOR_TRIPLER
: The SMS message that the tripler receives when they reply 'no' to the system.REJECTION_SMS_FOR_AMBASSADOR
: The SMS message that the ambassador receives when one of their triplers replies 'no' to the system.STRESS_TESTING
: If set to true, this allows the client to sign in as any external ID, without authentication. Never set this in production!EXCLUDE_UNREG_EXCEPT_IN
: Exclude unregistered voters except in these comma-separated 2-char states.SEARCH_TRIPLER_MAX_DISTANCE
: Distance constraint on tripler searchPAYOUT_BATCH_SIZE
: How many payouts to attempt per jobPAYOUT_CRON_STRING
: Define the payout cron jobUPGRADE_SMS_CRON_STRING
: Define the upgrade sms cron jobTWILIO_MSG_SVC_SID
: The SID for the Twilio messaging serviceNEO4J_ENCRYPTION
: Whether or not the neo4j encryption is enabledHUBSPOT_API_KEY
: The API key for HubSpotALLOY_KEY
: The API key for Alloy Verify APIALLOY_SECRET
: The API secret for Alloy Verify APIALLOW_BONUS
: Defines if we are allowing upgrade bonus payments for triplers who upgrade to become ambassadors (upgrades identified by matching phone numbersAMBASSADOR_EKATA_THRESHOLD
: Number defining how many of the following parameters must have a match from Ekata on ambassador signup in order for the ambassador to not accrue an ambassador_ekata_blemish - first name, last name, first 4 characters of address for that phone numberAMBASSADOR_EKATA_PENALTY
: Number defining how many ambassador_ekata_blemish points are accrued by the ambassador when they do not reach the above theresholdTRIPLER_EKATA_PENALTY
: Number defining how many tripler_ekata_blemish points are accrued by the ambassador when a Tripler they contacted does not have any matches for first name, last name nor address in Ekata data returned for the Tripler's phone numberTRIPLER_EKATA_BONUS
: Number defining how many tripler_ekata_blemsih points are deducted for for the ambassador when a Tripler they contacted DOES have matches for first name, last name or address in Ekata data returned for the Tripler's phone numberSHORT_LINK_BASE_URL
: "www.blockpower.vote" - Sets the URL for BallotReady links (or other links) sent in text messagesVOTING_PLAN_SMS_FOR_TRIPLER
: Copy for SMS sent to a tripler with their custom BallotReady URLVOTING_PLAN_SMS_FOR_AMBASSADOR
: Copy for SMS sent to a ambassador with their custom BallotReady URLNEEDS_ADDITIONAL_1099_DATA_TRIPLER_DISBURSEMENT_LIMIT
: Threshold of total pending + disbursed + settled (settled is used for PayPal only) payouts after which an ambassador must complete the Stripe 1099 flow to provide SSN and DOB to Stripe. Set in cents, e.g. 45000 = $450 of total earningsCLIENT_BASE_URI:
: Base URL to return ambassador to following completion of above Stripe flowFRAUD_THRESHOLD
: Amount of fraud points after which an ambassador's account will automatically be lockedTRIPLER_SEARCH_NAME_BOOST
: Number, e.g. "5". Factor by which we weight name matchiness in Tripler search results