2019-01-24 12:17:24 -08:00
|
|
|
|
# ZF Grants Backend
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
2019-01-24 12:17:24 -08:00
|
|
|
|
This is the backend component of [grants.zfnd.org](http://grants.zfnd.org).
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
2018-10-19 15:20:51 -07:00
|
|
|
|
## Environment Setup
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
|
Run the following commands to bootstrap your environment.
|
|
|
|
|
Note: db setup is configured in .env when running locally. SQLLite is used by default in /tmp/
|
|
|
|
|
|
|
|
|
|
# Get python in a virtual environment
|
|
|
|
|
virtualenv -p python3 venv
|
|
|
|
|
source venv/bin/activate
|
|
|
|
|
|
|
|
|
|
# Install python requirements
|
|
|
|
|
pip install -r requirements/dev.txt
|
|
|
|
|
|
|
|
|
|
# Create environment variables file, edit as needed
|
|
|
|
|
cp .env.example .env
|
|
|
|
|
|
2018-10-19 15:20:51 -07:00
|
|
|
|
If you want emails to work properly, you'll both need a SendGrid secret api key in `.env`,
|
|
|
|
|
and if you’re running Python 3.6+ on macOS, you'll need to
|
|
|
|
|
[fix your certificates](https://stackoverflow.com/a/42334357).
|
|
|
|
|
|
|
|
|
|
## Database Setup
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
|
Once you have installed your DBMS, run the following to create your app's
|
|
|
|
|
database tables and perform the initial migration
|
|
|
|
|
|
|
|
|
|
flask db migrate
|
|
|
|
|
flask db upgrade
|
|
|
|
|
|
2019-01-16 21:20:10 -08:00
|
|
|
|
## Generate Admin Authentication
|
|
|
|
|
|
|
|
|
|
To generate a new admin password, run
|
|
|
|
|
|
|
|
|
|
flask flask gen-admin-auth
|
|
|
|
|
|
2018-09-10 09:55:26 -07:00
|
|
|
|
## Running the App
|
2018-12-14 11:36:22 -08:00
|
|
|
|
|
2018-10-19 22:18:27 -07:00
|
|
|
|
Depending on what you need to run, there are several services that need to be started
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
|
If you just need the API, you can run
|
|
|
|
|
|
|
|
|
|
flask run
|
|
|
|
|
|
|
|
|
|
## Deployment
|
|
|
|
|
|
|
|
|
|
To deploy
|
|
|
|
|
|
|
|
|
|
export FLASK_ENV=production
|
|
|
|
|
export FLASK_DEBUG=0
|
|
|
|
|
export DATABASE_URL="<YOUR DATABASE URL>"
|
|
|
|
|
flask run # start the flask server
|
|
|
|
|
|
2018-12-14 11:36:22 -08:00
|
|
|
|
In your production environment, make sure the `FLASK_DEBUG` environment
|
|
|
|
|
variable is unset or is set to `0`.
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
|
## Shell
|
|
|
|
|
|
|
|
|
|
To open the interactive shell, run
|
|
|
|
|
|
|
|
|
|
flask shell
|
|
|
|
|
|
2018-12-14 11:36:22 -08:00
|
|
|
|
By default, you will have access to the flask `app`.
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
|
## Running Tests
|
|
|
|
|
|
|
|
|
|
To run all tests, run
|
|
|
|
|
|
|
|
|
|
flask test
|
|
|
|
|
|
CCRs (#86)
* CCRs API / Models boilerplate
* start on frontend
* backendy things
* Create CCR redux module, integrate API endpoints, create types
* Fix/Cleanup API
* Wire up CreateRequestDraftList
* bounty->target
* Add 'Create Request Flow' MVP
* cleanup
* Tweak filenames
* Simplify migrations
* fix migrations
* CCR Staking MVP
* tslint
* Get Pending Requests into Profile
* Remove staking requirement
* more staking related removals
* MVP Admin integration
* Make RFP when CCR is accepted
* Add pagination to CCRs in Admin
Improve styles for Proposals
* Hookup notifications
Adjust copy
* Simplify ccr->rfp relationship
Add admin approval email
Fixup copy
* Show Message on RFP Detail
Make Header CTAs change based on draft status
Adjust proposal card style
* Bugfix: Show header for non signed in users
* Add 'create a request' to intro
* Profile Created CCRs
RFP CCR attribution
* ignore
* CCR Price in USD (#85)
* init profile tipjar backend
* init profile tipjar frontend
* fix lint
* implement tip jar block
* fix wrapping, hide tip block on self
* init backend proposal tipjar
* init frontend proposal tipjar
* add hide title, fix bug
* uncomment rate limit
* rename vars, use null check
* allow address and view key to be unset
* add api tests
* fix tsc errors
* fix lint
* fix CopyInput styling
* fix migrations
* hide tipping in proposal if address not set
* add tip address to create flow
* redesign campaign block
* fix typo
* init backend changes
* init admin changes
* init frontend changes
* fix backend tests
* update campaign block
* be - init rfp usd changes
* admin - init rfp usd changes
* fe - fully adapt api util functions to usd
* fe - init rfp usd changes
* adapt profile created to usd
* misc usd changes
* add tip jar to dedicated card
* fix tipjar bug
* use zf light logo
* switch to zf grants logo
* hide profile tip jar if address not set
* add comment, run prettier
* conditionally add info icon and tooltip to funding line
* admin - disallow decimals in RFPs
* fe - cover usd string edge case
* add Usd as rfp bounty type
* fix migration order
* fix email bug
* adapt CCRs to USD
* implement CCR preview
* fix tsc
* Copy Updates and UX Tweaks (#87)
* Add default structure to proposal content
* Landing page copy
* Hide contributors tab for v2 proposals
* Minor UX tweaks for Liking/Following/Tipping
* Copy for Tipping Tooltip, proposal explainer for review, and milestone day estimate notice.
* Fix header styles bug and remove commented out styles.
* Revert "like" / "unfollow" hyphenication
* Comment out unused tests related to staking
Increase PROPOSAL_TARGET_MAX in .env.example
* Comment out ccr approval email send until ready
* Adjust styles, copy.
* fix proposal prune test (#88)
* fix USD display in preview, fix non-unique key (#90)
* Pre-stepper explainer for CCRs.
* Tweak styles
* Default content for CCRs
* fix tsc
* CCR approval and rejection emails
* add back admin_approval_ccr email templates
* Link ccr author name to profile in RFPs
* copy tweaks
* copy tweak
* hookup mangle user command
* Fix/add endif in jinja
* fix tests
* review
* fix review
2019-12-05 17:01:02 -08:00
|
|
|
|
To run only select test, Flask allows you to match against the test filename with ``-t` like so:
|
|
|
|
|
|
|
|
|
|
flask test -t proposal
|
|
|
|
|
|
2018-09-10 09:55:26 -07:00
|
|
|
|
## Migrations
|
|
|
|
|
|
|
|
|
|
Whenever a database migration needs to be made. Run the following commands
|
|
|
|
|
|
|
|
|
|
flask db migrate
|
|
|
|
|
|
|
|
|
|
This will generate a new migration script. Then run
|
|
|
|
|
|
|
|
|
|
flask db upgrade
|
|
|
|
|
|
|
|
|
|
To apply the migration.
|
|
|
|
|
|
2018-12-14 11:36:22 -08:00
|
|
|
|
For a full migration command reference, run `flask db --help`.
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
|
|
|
|
## Commands
|
2018-12-14 11:36:22 -08:00
|
|
|
|
|
2019-02-28 16:26:38 -08:00
|
|
|
|
To create a proposal
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
2019-02-07 04:40:32 -08:00
|
|
|
|
flask create-proposal "FUNDING_REQUIRED" 1 123 "My Awesome Proposal" "### Hi! I have a great proposal"
|
|
|
|
|
|
2019-02-28 16:26:38 -08:00
|
|
|
|
To seed many proposal
|
2019-02-07 04:40:32 -08:00
|
|
|
|
|
|
|
|
|
flask create-proposals <number_of_proposals:int>
|
|
|
|
|
|
2019-02-28 16:26:38 -08:00
|
|
|
|
To set a user to admin
|
|
|
|
|
|
|
|
|
|
flask set-admin <email|id>
|
|
|
|
|
|
2018-09-10 09:55:26 -07:00
|
|
|
|
|
2018-12-14 11:36:22 -08:00
|
|
|
|
## S3 Storage Setup
|
|
|
|
|
|
|
|
|
|
1. create bucket, keep the `bucket name` and `region` handy
|
|
|
|
|
1. unblock public access `Amazon S3 > BUCKET_NAME > Permissions > Public access settings`
|
|
|
|
|
1. set the CORS configuration, replace HOST_NAME with desired domain, or `*` to allow all
|
|
|
|
|
Amazon S3 > BUCKET_NAME > Permissions > CORS configuration
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
|
|
|
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
|
|
|
|
|
<CORSRule>
|
|
|
|
|
<AllowedOrigin>HOST_NAME</AllowedOrigin>
|
|
|
|
|
<AllowedMethod>GET</AllowedMethod>
|
|
|
|
|
<AllowedMethod>POST</AllowedMethod>
|
|
|
|
|
<AllowedMethod>PUT</AllowedMethod>
|
|
|
|
|
<AllowedHeader>*</AllowedHeader>
|
|
|
|
|
</CORSRule>
|
|
|
|
|
</CORSConfiguration>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
1. create IAM Policy, replace `BUCKET_NAME` with correct name.
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
{
|
|
|
|
|
"Version": "2012-10-17",
|
|
|
|
|
"Statement": [
|
|
|
|
|
{
|
|
|
|
|
"Effect": "Allow",
|
|
|
|
|
"Action": [
|
|
|
|
|
"s3:PutObject",
|
|
|
|
|
"s3:PutObjectAcl",
|
|
|
|
|
"s3:GetObject",
|
|
|
|
|
"s3:DeleteObject"
|
|
|
|
|
],
|
|
|
|
|
"Resource": [
|
|
|
|
|
"arn:aws:s3:::BUCKET_NAME/*"
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
1. create IAM user with programatic access (Access key) and assign that user the policy created above
|
|
|
|
|
1. copy the user's `Access key ID`, `Secret access key`, `bucket name` & `bucket region` to private `.env`, see `.env.example`
|
2019-01-02 10:23:02 -08:00
|
|
|
|
|
|
|
|
|
## Social Verification (oauth)
|
2019-01-16 21:20:10 -08:00
|
|
|
|
|
2019-01-02 10:23:02 -08:00
|
|
|
|
These instructions are for `development`, for `production` simply replace all hostnames/ips/ports with the proper production hostname.
|
|
|
|
|
|
2019-03-14 13:29:02 -07:00
|
|
|
|
1. Create GitHub oauth app https://github.com/settings/developers
|
2019-01-16 21:20:10 -08:00
|
|
|
|
|
|
|
|
|
1. select tab **OAuth Apps** > click **New OAuth App** button
|
|
|
|
|
1. set **Homepage URL** to `http://localhost:3000`
|
|
|
|
|
1. set **Authorization callback URL** to `http://localhost:3000/callback/github`
|
|
|
|
|
1. save **Client ID** and **Client Secret** to `.env` `GITHUB_CLIENT_ID` & `GITHUB_CLIENT_SECRET` respectively.
|
2019-01-02 10:23:02 -08:00
|
|
|
|
|
|
|
|
|
1. Create Twitter oauth app https://developer.twitter.com/en/apply/user
|
2019-01-16 21:20:10 -08:00
|
|
|
|
|
|
|
|
|
1. click **Create an App**
|
2019-01-24 12:17:24 -08:00
|
|
|
|
1. set **Website URL** to a valid URL, such as `http://grants.zfnd.org`
|
2019-01-16 21:20:10 -08:00
|
|
|
|
1. check the **Enable Sign in with Twitter** option
|
|
|
|
|
1. set **Callback URLs** to `http://127.0.0.1:3000/callback/twitter`
|
|
|
|
|
1. fill out other required fields
|
|
|
|
|
1. after create, select **Keys and tokens** tab
|
2019-03-14 13:29:02 -07:00
|
|
|
|
1. save **Consumer API key** and **Consumer API secret key** to `.env` `TWITTER_CLIENT_ID` & `TWITTER_CLIENT_SECRET` respectively.
|