Giter VIP home page Giter VIP logo

main's Introduction

Affinity

Affinity.works is supporting the surge of resistance against Trump. It's coming at it in two ways. First, working with the new activist groups that have sprung up, building MVP's to solve the problems they've encountered in their organizing. Second, Affinity is enabling rapid collaboration between the grassroots and the big national networks like Indivisible & Daily Kos, to defend the institutions of democracy.

Concretely, the tool is a SaaS and has components for managing a network of groups, a crm, task management for volunteers, outreach, and a reputation marketplace between campaigns, activists, and groups.

Developers

Getting Started

Clone the project:

$ git clone https://github.com/affinityworks/main
$ cd main

Or (via ssh):

$ git clone [email protected]:affinityworks/main.git
$ cd main

The project requires the following system-level dependencies:

  • postgresql v 9.6: our database!
  • redis v 4.0.6: a cache to store frequently-retrieved things in memory instead of on disk
  • ruby v 2.3.3: the programming language in which the bulk of the app is written
  • nodejs v 6.9.0: enables us to transpile "es6"-flavored js into js that will run in all browsers
  • bundler v 1.x: the package manager for ruby
  • yarn v 1.x: yet another javacript package manager

Below are some scripts for installing and running those dependencies using either Docker or plain old bash scripts. Feel free to take a look at Dockerfile, dockercompose-yml file, or the run and install scripts in the bin directory to get a sense of what's going on under the hood!

All commands assume you are located in path/to/this/repo.

Docker Setup

Install docker and docker-compose, then...

Run app:

$ ./bin/docker-up

Run in background:

$ ./bin/docker-up -d

Shut down:

$ ./bin/docker-down

Run tests:

$ ./bin/docker-cmd "bundle exec rails test"

Run arbitrary bash commands:

$ ./bin/docker-cmd "bundle exec rake routes"

Rebuild docker container:

$ ./bin/docker-build "latest"
$ docker push affinityworks/web:latest

Bash setup

Note: our bash scripts only work for Mac OSX and Debian-flavored GNU/Linux. They also enforce use of both NVM and RVM. If those constraints don't work for you, please feel free to either:

  1. Use the Dockerized dev env described above.
  2. Adapt the comands in our bash scripts to your liking.
  3. Open an issue or pull request to help us improve the scripts! :)

Install:

$ ./bin/install

Run:

$ ./bin/run-services # first run only: start redis & postgres
$ ./bin/copy_configs # first run only: see `Secrets` section below
$ ./bin/seed-db # first run only: seed db
$ ./bin/run

Shut down cleanly:

$ kill -9 `cat tmp/pids/server/pid`

Run tests:

$ bundle exec rails test

Gotchas

Switching btw/ docker and bash

If you are switching between docker and bash setups, you might run into odd Devise authentication errors on login. If this happens:

Delete all caches:

$ cd path/to/this/repo
$ rm -rf tmp/caches/

If that doesn't fix it, try removing the local dbs and re-seeding:

$ psql
# drop database affinity_development;
# drop database affinity_test;
# \q
$ ./bin/seed-db

Secrets Management

Secrets For Community Contributors

We provide sample versions of encrypted config files. They are in the config folder with names like some_config.yml.exampl. For the app to run, you need to copy them all to files with names like some_config.yml, which you can do by running the following script:

$ ./bin/copy_configs

If you would like to gain access to the encrypted credentials:

Secrets For Team Members

Blackbox

We use blackbox for secrets management.

It allows us to keep credentials under secure version control by:

  • maintaining a list of sensitive files
  • gitingoring the files
  • encrypting the files to a whitelist of PGP keys
  • allowing key-owners to decrypt and re-encrypt files with easy-to-remember commands

To use it, you will first need:

  • a PGP key (If you don't have one, we recommend GPGSuite for Mac users, and this guide from Riseup for Linux or Windows users)
  • an admin to add your PGP public key to the whitelist at keyrings/live/blackbox-admins.txt

Now you can use the following commands:

Decrypt all files:

$ ./bin/blackbox_decrypt_all_files

Encrypt a newly created file:

$ ./bin/blackbox_register_new_file some_file_name.yml

Edit an encrypted file:

$ ./bin/blackbox_edit_start some_file.yml.gpg
<do your editing>
$ ./bin/blackbox_edit_end some_file.yml

Edit an already-decrypted file:

<do your editing>
$ ./bin/blackbox_edit_end some_file.yml

Delete all cleartext files:

$ ./bin/blackbox_shred_all_files

Add new public key to whitelist:

$ ./bin/blackbox_addadmin
$ ./bin/blackbox_shred_all_files
$ ./bin/blackbox_update_all_files # re-encrypts to new whitelist

Blackbox is all just shell commands! You can read them in ./bin. If you'd like to install them on your machine so you can type blackbox_some_command instead of `./bin/blackbox_some_command**, you can:

Install blackbox on your $PATH:

$ git clone [email protected]:StackExchange/blackbox.git
$ cd blackbox
$ make copy-install
$ cd ../ && rm -rf blackbox

Importing Partner Credentials

To import Gsuite credentials for a partner group, first:

  • make sure the group is part of a network listed in config/networks.yml
  • place a copy of the network's service_account.json file in lib/imports/gsuite
  • rename the file to some_network_google_gsuite_key.json (where some_network is the snakecased version of the network's name given in networks.yml)

Then run:

$ rake import_keys:gsuite

This will:

  • place an encrypted version of the credentials in a nested folder of lib/network_credentials
  • delete and gitignore all unencrypted versions
  • automatically create a new commit to place the above changes under version control

You will likely want to amend that commit to change the commit message.

Updating networks.yml

To update the list of networks:

  • decrypt it with ./bin/blackbox_edit_start config/networks.yml if necessary
  • add networks, groups, and organizers following the format in the file
  • re-encrypt the config file with ./bin/blackbox_edit_end config/networks.yml
  • create a migration with rake config:update_networks as the body of the change method
  • run rake db:migrate and rake db:migrate RAILS_ENV=test
  • commit your changes and push them

Build Javascript in Production Configuration

Webpack will automatically rebuild the dev javascript bundles on changes according to the development configuration in client/webpack.config.js. So it is not necessary to rebuild manually. That said, if you want to spit out a static build of the frontend that matches the production build, you can run:

$ bundle exec rake react_on_rails:assets:webpack

Configuration Note: Mailgun + Heroku

Configuring the Heroku Mailgun addon is not that fun. Hopefully you never have to do it!

Just in case you do, here is a near-exhaustive list of the steps involved in doing so:

  1. Provision the Mailgun add-on (in the "Resources" tab of the dev-affinityworks app panel)
  2. Click on it (to go to the mailgun dashboard)
  3. Verify the mailgun account via email or help ticket (help ticket will be necesary if they send email to weird address)
  4. Creating new domain mg-dev.affinity.works
  5. Verify the domain by: a. clicking "Domains" -> "Domain Verification & DNS" b. observing the two TXT records that appear c. logging into gandi.net and finding the DNS records d. creating two TXT records with the values observed in step b above

Heroku Pipeline/CI/ENV

Heroku Pipeline

The current pipeline has 3 stages: Review -> Staging -> Production

Review

Build: Built automatically by any new Pull Requests.

Env: Pulls all environment variables from the Staging app environment in Heroku.

Arity: There will be one Review app for each PR until the PR is merged, upon which the Review app is destroyed.

Staging

Build: Built automatically upon any new merges of Pull Requests into master.

Env: Gets environment variables from the file .env.heroku/staging-affinityworks.

Arity: Only one Staging app.

Production

Build: Production is built manually built upon promoting Staging.

Env: Gets environment variables from the file .env.heroku/affinityworks

Arity: Currently there is one general Production app, as well as one client specific Production app.

Heroku CI

Description: The Heroku CI is currently set up to run automatically upon any of the following conditions: a push to an open Pull Request, a merge of a PR into master, a promotion from one app in the pipeline up to the next (such as from staging to production).

Build: The Heroku CI build pays attention to the environments: test section of app.json in this repo. This section contains both the test-setup script to run before running the tests as well as the test script for actually executing the tests.

Env: Gets environment variables from settings panel in the Settings panel of the Pipeline, under the section Heroku CI.

Heroku ENV

To add a new environment variable to all of the Heroku apps, follow these steps:

  1. Add the variable and its value to all of the files listed in config/heroku.yml
  2. Run the command rake heroku:export_vars from the command line
  3. Ensure that the variable has been added to each environment by running the command heroku config:get $VAR -a $ENV where $VAR is the name of the variable and $ENV is one of the envs listed in heroku.yml

main's People

Contributors

aguestuser avatar agustinrhcp avatar arnolfontalvo avatar benvoluto avatar chloealxandra avatar harpojaeger avatar hypernormal avatar jlev avatar jonathanedelman avatar matinieves avatar matt-holland avatar mgreich avatar nice00xt avatar rabble avatar rebeccaryang avatar scottwillson 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

Watchers

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

main's Issues

[import]: assign AffinityID to imported people

Especially to enable our "privacy aware" features, we need a unique ID for each person in our database (DIFFERENT from the way ActionNetwork works, using email as the ID).

We've decided to do this by using a hash of the primary email address as the AffinityID. This way we can always find someone in our system if a foreign system has their email, and if WE have their email in our special "Personally Identifiable Data" store we can match to the more public data store, but we DON'T keep their email address in the "more public" data store at all.

Upload event attendee list

The goal is:

  1. to receive a CSV or similar text file containing the names, email addresses, and/or other information about people who attended an event

  2. match those people to existing records in that group's list, and if not,

  3. create new person records with that data and then

  4. mark that person as "attended" to the event which was selected for the upload

Issues to resolve: datafile format, what is required vs. disallowed, how to allow the user to verify a "match" to an existing person.

implement groups admin view

We have a mockup for groups admin. Some of the groups controller exists. Make the groups controller match the mockup.

Triggers for re-render of event list

Sometimes a user will be working with the event list, when the underlying data changes. For example another user will delete an event which is in the user's list, or the date/time will be changed, etc.

How will we become aware of these changes, and re-display the event list for the user?

Triggers for re-render of RSVP list

Similar to #53 , sometimes a user will be working with the list of RSVPs for an event, when the underlying data changes. For example another user will delete an existing RSVP, or a new RSVP will be added, etc.

How will we become aware of these changes, and re-display the RSVP list for the user?

solve "de-duplication"

scenario: we've pulled over the member records for people who have RSVP'd to an event. Then the organizer uploads a csv file of attendees that they captured at the event. The imported file includes some of the same people who RSVP'd, and for some of those people it has additional and/or different information than what is in Action Network.

  1. how do we avoid displaying the same person twice on the Affinity event attendance page?
  2. how can we best get the new/changed information back into Action Network?
  3. should we import the people first into AN, rely on their "by email" de-duping, and then refresh the list of RSVP's by re-pulling it from AN?

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.