Giter VIP home page Giter VIP logo

amplify's People

Contributors

ahn-nath avatar alex-is-gonzalez avatar ankitagrawal98 avatar beexiong avatar computate avatar davidchapuis avatar dependabot[bot] avatar dietbepis1 avatar dmilburn avatar dunridge avatar eprice555 avatar hamdaankhalid avatar jamesmgreene avatar joey-ma avatar lingeorge88 avatar loopfruits avatar mahrsbar avatar manishapriya94 avatar mariah622 avatar nawazkhan avatar paramsiddharth avatar rcmtcristian avatar rsensenig avatar sammychinedu2ky avatar saumildhankar avatar shangguanwang avatar smgraywood avatar tdo95 avatar thyeggman avatar waldnzwrld 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

Watchers

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

amplify's Issues

Customize OpenAPI Schema

Use the following framework for

  • Cicero API
  • Lob API
  • Auth0 API

Context:

Here’s a good basic structure documentation site, but the official specification is pretty easy to follow.

The root file must contain a few objects:

  • The root OpenAPI object which also contains a general Info object that contains a title, version, licensing, contact information, and a link to the Pages site (externalDocs), also ToS or other stuff.
    Server URL/base path configuration
  • And then each API has paths /root/user and those paths have actions root/user/get

We probably want to have as many re-usable parts as possible. We should define a list of them, but there are definitely a few that leap to mind:

  • Schemas - contain the reusable ones in one place, like Address, every API probably needs the user’s address, or username.

  • Responses - generic “success” or “404” or other messages we don’t want to write out 5000 times

  • Error - something went wrong and we don’t know what. Used when other, specifically written error messages do not apply. (case-else)

  • What to we need to know if we need to define a security scheme (authentication/authorization), or if we’re even using any - that might be handled completely elsewhere, like by GitHub itself?

  • Documentation should cover any HTTP error responses that are likely to happen and include instructions on how to remedy it and the “200 success” code.

  • The APIs we are using, not writing, may have their own OpenAPI files already available, so we can potentially copy their stuff into our stuff rather than write it all up from scratch. Not sure what the plan is to keep all that up to date, though. If they change their stuff that we rely on, how do we know?

This template doesn’t include complete coverage of all possible OpenAPI fields, but it’s useful as starter code. In most cases you’ll want to add your own response schemas and reusable components. You can dig into the OAS specification itself or see our OpenAPI and Swagger examples below.

openapi: "3.0.0"
info:
  version: 1.0.0 // Version of your API
  title: Your API Title
  description: An API description template
  contact:
    name: Your Name
    email: [email protected]
    url: http://example.com
  license:
    name: License Name
    url: http://example.com/license-url
servers:
  - url: http://api.example.com
paths:
  /your_endpoint:
    get:
      description: |
        Multi-line description
        of your API endpoint
      operationId: yourOperation
      parameters:
        - name: your_param
          in: query
          description: Description of your param
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Your success description

Batch: Provide photos (and more info) for representatives

We are currently using the Google Civic API to look up relevant state and federal representative information based on the user's address. This works very well! 🎉

However, the Civic API is also missing quite a bit of information about those representatives, often including their photos and sometimes even information contact information. 😭

One strategy that we could employ to workaround this shortcoming is to stitch the information provided by the Google Civic API with information provided by other public APIs, such as the Open States database: https://docs.openstates.org/api-v3/ 🔀

I'm unsure of its completeness (it seems pretty thorough at first glance) but it's definitely better than relying on just the incomplete information from the Google Civic API. 😓

Templates for Campaign 3 don't load proper letter template

Issue

When selecting Campaign 3, entering a zip code (I used 27517), and selecting a representative, the application calls out to https://murmuring-headland-63935.herokuapp.com/api/lob/templates/tmpl_1057bb3e23kwkkq which yields a 400 error code. The outcome is that the screen shows two single quotes where the name and corresponding address for the selected representative should be displayed.

What screen is this?

This is the Campaign screen right after you submit a zip code. See the attached screenshot below.
Screen Shot 2022-02-10 at 3 02 50 PM

Which component? Which piece of copy or graphic?

Looks like src/components/RepresentativeCard.vue but I'm not 100%.

What is the change proposed? (add a figma screenshot, follow the workflow here)

  • Briefly describe the bug's user-visible impact in the title
  • If possible, include reproduction steps using the template below.
  • If this is an API bug, please include curl commands and output if possible.
  • If this is a visual bug, please include a screenshot or a GIF.
  • Content bug
  • Record any ideas you have as to the cause of the problem or how to fix it.
  • Add any labels that you might think are relevant to the problem.

Steps to reproduce:

  1. Select the ClimateCare campaign card (this should be Campaign ID 3) and click the VIEW CAMPAIGN button
  2. Enter a zip code and hit the Submit button

Actual behaviour:

The application calls out to https://murmuring-headland-63935.herokuapp.com/api/lob/templates/tmpl_1057bb3e23kwkkq which yields a 400 error code. The outcome is that the screen shows two single quotes where the name and corresponding address for the selected representative should be displayed.

Expected behaviour:

The name and corresponding address for the selected representative should be displayed immediately underneath the date.

Which topic does this educate the constituent around? (add a short description on how its clearer than the original) ?

Advocacy values to consider:

  • Testimonials should be personal
  • Language should be simple
  • People are lead by causes and their impact
  • Accessibility across abilities

What are frontend tasks? (if theres any tasks needed outside of the template below, pick a different color like blue)

  • Add image here in this file
  • Insert copy in this file

List files that need to be changed next to task

CC: @frontend-team member, @frontend-coordinator, @research-coordinator


For Coordinator

  • add appropriate labels: "good-first-issue", "design", "screen label", "intermediate"
  • assign time label
  • Approved and on project board

Bug: Awkward word-wrapping for campaign names

Some of the newer campaigns we've added for Sunrise have longer names. Some of these are exhibiting some awkward word-wrapping, e.g.:

image

It would be ideal if we could avoid that. ✨

Batch: Setting up Mayhem API

Purpose

This workflow starts your API and fuzzes it with ForAllSecure Mayhem for API
to find reliability, performance and security issues before they reach
production.

To use this workflow, you will need to:

  1. Create a Mayhem for API account at
    https://mayhem4api.forallsecure.com/signup

  2. Create a service account token mapi organization service-account create <org-name> <service-account-name>

  3. Add the service account token as a secret in GitHub called "MAPI_TOKEN"

  4. Update the "Start your API" step to run your API in the background before
    starting the Mayhem for API scan, and update the api-url & api-spec
    field.

If you have any questions, please contact us at [email protected]

name: "Mayhem for API"

on:
  push:
    branches: [ main ]
  pull_request:
    # The branches below must be a subset of the branches above
    branches: [ main ]

jobs:
  mayhem-for-api:
    name: Mayhem for API
    # Mayhem for API runs on linux, mac and windows
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write
    steps:
      - uses: actions/checkout@v2

      # Run your API in the background. Ideally, the API would run in debug
      # mode & send stacktraces back on "500 Internal Server Error" responses
      # (don't do this in production though!)
      - name: Start your API
        run: ./run_your_api.sh & # <- ✏️ update this

      - name: Mayhem for API
        uses: ForAllSecure/mapi-action@193b709971cc377675e33284aecbf9229853e010
        continue-on-error: true
        with:
          mapi-token: ${{ secrets.MAPI_TOKEN }}
          api-url: http://localhost:8080 # <- ✏️ update this
          api-spec: http://localhost:8080/openapi.json # <- ✏️ update this
          duration: 60
          sarif-report: mapi.sarif

      - name: Upload SARIF file
        uses: github/codeql-action/upload-sarif@v1
        with:
          sarif_file: mapi.sarif

Epic: ORM for database modeling and migrations

My experiences with Sequelize have all become cautionary tales, so I guided us away from using it at this point and instead favored just using Knex, which is a more basic "SQL query builder".

However, for maintainability's sake, it is probably worthwhile to consider an ORM for the long-term, especially with some contributors not being too familiar with databases.

I would suggest we investigate Prisma as a potential ORM in particular. 🔺

I think it has a lot of nice features that make it a more solid choice than Sequelize. It should also be able to completely replace our Knex usage, as far as I can tell at this point.

Tasks

  • Install Objection in the codebase: npm install --save objection
  • Configure Objection in the codebase
    • This requires a one-time configuration something like require('objection').Model.knex(knexClient)
  • #141
  • #142
  • BONUS: #143 (:warning: currently unused)
  • BONUS: Create a Model for the constituents table (:warning: currently unused)
  • BONUS: Create a Model for the sent_letters table (:warning: currently unused)
  • BONUS: Create a Model for the variants table (:warning: currently unused)

Status

  • There is a branch created called objection-orm that installs the objection module and sets up the project for creating models.
  • Feel free to create branches off that branch and send PRs to it as the base branch
  • Models should be created in the server/db/models/ directory (only exists in the objection-orm branch)
  • Model filename should be in a singular (not plural) form in all lowercase letters with hyphens as needed, e.g. letter-version.js
  • Model class name should in a singular (not plural) form in PascalCase letters, e.g. LetterVersion

Example, at filename server/db/models/letter-version.js:

const Model = require('./_base')

class LetterVersion extends Model {
  static get tableName() {
    return 'letter_versions'
  }

  // ...additional methods, relationships, etc.
}

module.exports = LetterVersion

[Test]: Stripe API integration tests

Payment/Donation

User stories:

  • Constituent pays a default of 1.00 (close to a forever stamp) which offsets the use of APIs like Lob, Stripe, and Cicero to mail the letter
  • Constituent can select a donation amount to support their cause further
  • A progress bar creates a visual incentive of the goal to support

QA
Files: In checkout.js for functions and checkout.test.js for tests

  • Add tests for Payment Intents
    • Copilot prompt: How can I handle errors or exceptions in the payment intent logic?
  • Add tests for server side code
    • Copilot prompt: How can I handle errors when making API requests in JavaScript?
  • Add tests for Charges
    Copilot prompt: Create tests in jest for createCharge

Context:

Read more and find test cards

When using the Payment Intents API with Stripe’s client libraries and SDKs, ensure that:

  • Authentication flows are triggered when required (use the regulatory test card numbers and PaymentMethods.)
    • No authentication (default U.S. card): 4242 4242 4242 4242.
    • Authentication required: 4000 0027 6000 3184.
  • The PaymentIntent is created with an idempotency key to avoid erroneously creating duplicate PaymentIntents for the same purchase.
  • Errors are caught and displayed properly in the UI.

Charges API
When using the Charges API with Stripe’s client libraries and SDKs, ensure that:

  • The card Element is passed correctly to createToken in your submit handler.
  • In the response handler for createToken, card errors are handled and displayed properly.
  • Only valid tokens are passed to your server as part of payment form submission.

Server-side code
In your server-side code, ensure that:

  • All requests are being made successfully. You may find it useful to view your account’s events and logs as you test your integration.
  • All API errors are handled properly.
  • Relevant webhooks are handled correctly.

Backend: Stripe Implementation

We've decided to use the prebuilt checkout flow instead of the custom payment flow.

In order to this, we'll be using Vue-Stripe Checkout. This requires session creation in the back-end using the steps outlined in Vue Stripe documentation above and deleting the current checkout.js logic.

We also need to ensure createLetter in lob.js only works after a successful payment as seen below. Unsure if anything needs to be changed here if we're doing the prebuilt checkout flow as compared to the custom flow.

router.post('/createLetter', async (req, res) => {
  // Get description, to, and template_id from request body
  const { description, to, from, template_id, charge } = req.body || {}
  const lobApiKey = getLobApiKey()
  const lob = new Lob({ apiKey: lobApiKey })
  const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY)

  try {
    // Create Lob address using variables passed into route via post body
    const letter = await lob.letters.create({
      description: description,
      to: {
        name: to.name,
        address_line1: to.line1,
        address_line2: to.line2,
        address_city: to.city,
        address_state: to.state,
        address_zip: to.zip
      },
      from: from.address_id,
      file: template_id,
      color: false
    })

    res
      .status(200)
      .send({ expected_delivery_date: letter.expected_delivery_date })
  } catch (error) {
    // We'll need a stripe test env key to test this in our integration tests
    const refund = await stripe.refunds.create({
      charge: charge
    })
    // TODO handle error for refund error. Not doing this currently because chance of
    // user making it this far in the process and both LOB API and Stripe failing is very small.
    res.status(500).send({
      error: `Something failed! A refund of ${refund.amount} ${refund.currency} has been issued`
    })
  }
})

Hack Pod: Enhance Dev Experience via Codespaces + Secure Workflows

⬇️ Table of Contents:

User Story

Screen Shot 2022-04-14 at 2 49 53 PM

=- Our goal is to enable students towards enterprise architecture while making their onboarding painless

Current Contribution Flow and Actions

Today we use Actions to perform administrative automations, CI/CD, and use it for CodeQL (in pink)

image

  • Current workflows
    • checks formatting
    • Lint code
    • Lint workflows
    • Scorecards
    • CodeQL
    • Integration tests

Codespaces Specs and Tasks

Project View

Considerations

  • set up default container configuration
  • Adding additional features to your devcontainer.json file
  • How can we make it easier for outside collaborators that are new to open source provide their own API keys as secrets in order for the environment variables in codespaces to work?
    • Currently, this creates a barrier for new students who also have to learn concepts of APIs keys, and secrets for each API we use by going to each (4: Lob, Auth0, Google Civic, Stripe). What strategies do we want to have for people to route Auth0 (Even if the create their own key, how do we allow for that as a variable?
    • In particular, Auth0 callback is hard to configure for codespaces domains without each contributor having to create their own Auth0 account
  • Are there container specs that are needed?
  • Should we be adding any external lints for Docker?
  • Bonus: what gaps can the readme fill?

Resources:

Overall: Advocacy Header

What screen is this?

This is a header for multiple screens: 2-8

Which component? Which piece of copy or graphic?

Screen Shot 2022-01-20 at 8 56 08 PM

What is the change proposed? (add a figma screenshot, follow the workflow here)

  • How to standardize images from campaign cards into header
  • What pieces of information should be added:
    • information about the advocacy message as a more info button?
    • back button?
    • open to other functionality decisions!

Which topic does this educate the constituent around? (add a short description on how its clearer than the original) ?

Advocacy values to consider:

  • Testimonials should be personal
  • Language should be simple
  • People are lead by causes and their impact
  • Accessibility across abilities

What are frontend tasks? (if theres any tasks needed outside of the template below, pick a different color like blue)

  • Add image here in this file
  • Insert copy in this file

List files that need to be changed next to task

CC: @frontend-team member, @frontend-coordinator, @research-coordinator


For Coordinator

  • add appropriate labels: "good-first-issue", "design", "screen label", "intermediate"
  • assign time label
  • Approved and on project board

Subtask Send Letter: Checkout button

What screen is this?

Screen 7: Send Letter

Screen Shot 2022-01-20 at 8 57 08 PM

Which component? Which piece of copy or graphic?

The text on the final action button at the bottom
Screen Shot 2022-01-20 at 9 23 55 PM

What is the change propoosed? (add a figma screenshot, follow the workflow here)
Change words to simplify language but still convey you are doing 2 actions (payment via stripe and sending post)

Which topic does this educate the constituent around? (add a short description on how its clearer than the original) ?

Advocacy values to consider:

  • Testimonials should be personal
  • Language should be simple
  • People are lead by causes and their impact
  • Accessibility across abilities

What are frontend tasks? (if theres any tasks needed outside of the template below, pick a different color like blue)

  • Add image here in this file
  • Insert copy in this file

List files that need to be changed next to task

CC: @frontend-team member, @frontend-coordinator, @research-coordinator


For Coordinator

  • add appropriate labels: "good-first-issue", "design", "screen label", "intermediate"
  • assign time label
  • Approved and on project board

Epic Outline: Letter Payment

Context:

This is part of the features of the Letter Payment Epic OpenSourceFellows/amplify-front-end#45. The user is informed about the minimum cost of a letter and then offered donation options that can be checked out.
Screen Shot 2022-02-10 at 9 07 33 AM

To do:

  • Create a donation progress bar (user story here). This values are currently not available to us, so you can use placeholder values. Look into this progress bar vuetify component for help.
  • Create a checkbox that allows for user to receive a gift as seen above. This will not be stored anywhere at the moment.
  • Implement letter payment following these steps.
    The user story is as followed:
  • User picks a donation amount
  • User can choose to send letter without donation amount (value send to api would be '1'
  • User is directed to complete transaction via stripe checkout
  • Once payment is successful, letter is sent

Test API Contracts

Describing our APIs using OpenAPI is great, but if we want the description to remain complete and accurate, we need to test it! The good news is that if you’re using the api test helper, you get that testing for free.

Take this test, for example:

data = api :post, "/repositories/#{@repo.id}/check-runs", {},
input: {
name: "coverage-stuff",
head_sha: @sha,
status: "in_progress",
started_at: Time.now.utc,
}

assert_equal 200, last_response.status, last_response.body
The api method makes a call to our API and returns the data returned by the resource. By default every api test helper call goes through an OpenAPI validation middleware. A router takes the path you provide, matches the operation, and uses that operation to validate everything about that request (query parameters, response schemas, and more).

If a mismatch is detected by the middleware, it will raise, making your test fail with an helpful error. Imagine, for example, you added a new property called my_new_property to a serializer but forgot to add it to the OpenAPI description. If you have a test returning that new property, it would fail with an error like the following:

2021-03-09 00:00:00 - OpenApi::Validation::Error

Property my_new_property is not described by the response 200 for operation my/operation. This either means you forgot to describe that property in the operation description located at app/description/operations/my/operation.yml or that the test is wrong.

More info: https://thehub.github.com/engineering/development-and-ops/public-apis/openapi/contract-testing
There are plenty of validations like this one running when you use the api test method. Thankfully, each error should have enough information on how to fix it. If it doesn’t, open an issue or let us know in #ecosystem-api. Over time this means the OpenAPI description always reflects what happens at runtime, which means our documentation, SDKs, and any tooling that depends on OpenAPI will remain accurate!

##Legacy Behavior
Sometimes tests will fail due to a behavior that’s not described in OpenAPI but used in the test. Generally the failure indicates that we should document it in OpenAPI, but in some cases we’d rather not expose it externally. For example, some obscure and deprecated use case may fail a contract test, but we’d rather not expose it to our documentation and SDKs through the OpenAPI description.

In these cases we still want to describe that behavior in OpenAPI, but make sure it is not exposed anywhere else than in our own internal description. To do so, you can use the x-internal-only OpenAPI extension:

parameters:

  • name: legacy_param
    in: query
    schema:
    • type: string
      x-internal-only: true
      This will satisfy the contract tests, but won’t leak the existence of this parameter outside of github/github.

Skipping Contract Testing

On certain occasions you may find it necessary to skip OpenAPI contract testing

Skipping a specific test

It’s possible you may want to test an endpoint and disable the OpenAPI validation middleware. Sometimes a test is sending a wrong value, but you want to test the behavior of the endpoint, disregarding the extra OpenAPI contract testing layer. To do so, you can use skip_openapi_validation when calling the api helper:

data = api :get, "/users",
my_param: "not_supported",
skip_openapi_validation: "Skipping because we want to test the 422 returned when passing an unsupported param"

Skipping entire endpoints/resources

Additionally to the “per-test” OpenAPI skipping, It’s also possible to opt out an entire path from OpenAPI contract testing. Although we strive to have a 100% accurate description, sometimes internal or deprecated endpoints need to be ignored.

Add a regex for the paths you want to exclude from this OpenAPI validation in our IgnoreList.

User input office_div filter

Purpose: Have reps be filterable by jurisdiction: federal, state, county

Screen Shot 2021-05-22 at 6 18 28 PM

User Story:

  • Use button to filter representatives and shorten returned list of search for easier viewing

Tasks:

  1. Create buttons in campaign.vue view
  2. Have button filter by representative levels
    a. country = federal
    b. level 1 = state
    c. level 2 = county
  3. Only show representative array that corresponds

File to change: SearchReps line 17

Review Letter: Address Verification

This is a part of OpenSourceFellows/amplify-front-end#44 where after user inputs address, we use the Lob API address_verification method. The goal is to create address verification call on user input.

To do:

  • Update the api url to createAddress instead of addressVerification as it is currently
submit () {
            this.formHasErrors = false

            Object.keys(this.form).forEach(f => {
                if (!this.form[f]) this.formHasErrors = true

                this.$refs[f].validate(true)
            })

            axios.post('https://murmuring-headland-63935.herokuapp.com/api/lob/addressVerification', this.form)
                .then((response) => {
                    console.log(response)
                    this.message = 'Address verified!'
                    }
                })
                .catch(function (error) {
                    console.log(error)
                })
        }

  • On successful verification, store the address_id that is received from the createAddress request. This will used as the to variable in createLetter
  • Create a letter object using the createLetter api which adds the user to the addressbook in (https://docs.lob.com/#operation/create_address) and the following information from Lob. From will be the representative address that should already be accessible.

Screen Shot 2021-10-28 at 12 05 24 PM

Epic 6: Chatbot API

Open tasks

Use Case:

  • educates user on civic engagement
  • provides details around the piece of legislation
  • acts as an accessible FAQ

Screen Shot 2022-03-16 at 9 02 38 PM

Screen 1: Info on the bill and letter sending
Chat conversation starters:

  • default: enter your zipcode to begin
    when the chatbot is hovered over: menu of options show up
  • What is this bill about?
  • Why am I sending a letter?
  • Where can I learn more about the team?

Screen 2: Info on choosing reps

  • Why am I reaching out to representatives?
  • What does a local representative do?
  • What does a state representative do?
  • What does my congress member do?

Screen 3: FAQ around action inputs

  • Why their story matters
  • Why we use their address and how its protected
  • breakdown of dollar

Epic: Database Operations (Post ORM Backend Implementation)

This epic for earth day 4/21 has moved here

User Story:

  • User has authenticated
  • Has added their name into the signature box
  • Has added their address into the address box
  • User moves to next step (new window triggered) payment added
  • Successful payment triggers 'send message' button
  • Send message button creates a letter to send to the representative
    • Send message triggers a POST to back-end to make a call to LOB API
    • Successful 'send message' should also trigger a POST to back-end to save record into the DB

Development Task

Send User Letter to Lob

Save User Letter Data

  • Create Table in PostgresDB via KNEX migration
  • Seed User Letter Data
  • Create new endpoint /api/userletter endpoint
  • Add app.js route information for /api/userletter endpoint
  • Create GET function /api/userletter
  • Configure to return all user letters that have been created
  • OpenSourceFellows/amplify-back-end#124
  • Configure endpoint to accept JSON Objects with Letter information
  • Use Knex ORM to build insert query
  • Send 200 status code upon successful call to Front End
  • Add Documentation to Wiki Endpoint
  • Sample implementation in documentation

Create a Model for the `transactions` table

Create an Objection Model for the transactions table

  • Update its usage in server/routes/api/checkout.js
  • Consider adding any practical helper/accessor behavioral methods that seem relevant to our usage

Towards #32

Twilio integration for sms alerts

Context

Screen Shot 2022-04-19 at 12 45 07 PM

User Story:
A user can choose to opt into sms alerts around the cause they wrote a letter for. The twilio integration allows us to follow up with user education via SMS.

Screen Shot 2022-03-16 at 8 15 28 PM

  • Stage 1: Users are sent through social media campaign, at advocacy events, while canvassing through a QR code
  • Stage 2: Users authenticate (via Auth0 through their phone number)
  • Stage 3: Users sign up for updates when sending their letter
  • Stage 4: Send sms updates monthly from advocacy group (update the constituent table for people who signed up for sms updates)

Specs

  • Integrate Twilio

Screen Shot 2022-04-19 at 1 03 56 PM

  • Update Database

Screen Shot 2022-04-19 at 1 03 49 PM

  • Update API docs

References

Data Structure | Data Report
Feature Discussion
Twilio API Docs
User Journey Miro

Exit Criteria

  • Full User Story Discussion

Exit Criteria

Create a Model for the `campaigns` table

Create an Objection Model for the campaigns table

  • Update its usage in server/routes/api/campaigns.js
  • Consider adding any practical helper/accessor behavioral methods that seem relevant to our usage

Towards #32

Review Letter: Panel Transitioning Commands

Panel Transitioning commands

To ease the transitions across the 3 steps before sending letter, we want to use the 'enter command' to signify moving to the next step and implement locking for the accordion steps.
Screen Shot 2022-02-10 at 9 36 54 AM

Tasks

  • Create "next" buttons for each accordion panel
  • Create default, in progress and complete styles for the accordion as seen in the screenshot below:

Screen Shot 2022-02-10 at 9 40 59 AM

  • Implement functionality so user is required to complete the steps in order

Data in Transit: Lob letter cardinality

Description

Advocacy groups singly pointed out that customized letters help gather pivotal data points for impactful storytelling thats specific to localized solutions.

Screen Shot 2022-04-20 at 12 37 08 AM

Exit Criteria & References:

  • #360
  • #593
  • #707
  • Define letter template object #183
  • #708
  • Explore salting or hashing of content. Encrypt JSON string input by constituent via either UUID or salt entire string

User Story: How to encrypt data so we can aggregate and tell compelling stories based on communities: recommendations, experience, org affiliations, etc

  • User enters message to customize letter
  • Customized message is added to letter to be printed as a merge variable
  • Once letter is sent, a copy of the template is saved in our database
  • Personal User information related to the letter_sent is encrypted (name, email, number, address except for zipcode) so aggregates of data can be presented in a visual dashboard adhering to PII compliance

Screen Shot 2023-01-26 at 11 01 49 AM

Context & Considerations

  • slides 42-44
  • We use Objection.js to store current data structures
  • Currently our letter templates are stored in Lob. Lob sends paper mail. Lob.js file for Amplify
    • We have templates within Lob
    • We currently use retrieve to display the letter
    • We currently use post to create_letter and send
  • We need to hold this information in our ORM since Lob does not break down location further than state level
    We need to cache the customization of the letter if user wants to save their past work

Create a Model for the `letter_versions` table

Create an Objection Model for the letter_versions table

  • Update its usage in server/routes/api/letter_versions.js
  • Consider adding any practical helper/accessor behavioral methods that seem relevant to our usage

Towards #32

Use Heroku backend proxying for `/api` to support multiple backends

Alternative to, or stepping stone towards:


Currently, the frontend portion of our app contained hardcoded URL references to the current production instance of our backend portion's Heroku App, e.g.:

https://github.com/ProgramEquity/amplify/blob/f8f42e4bf0903694972b6bb81f3bd55682ec34fa/src/components/SearchReps.vue#L107-L109

This is highly restrictive to our continued development as the frontend is always referring to the production backend code, thus not allowing us to develop both the frontend and backend portions of a new feature within a single PR.

This also introduces risk when we discuss having dedicated deployments that will not be updated for special launch events such as:

  • ProgramEquity/product#39

If we cannot address this with #83 in the short term, one workaround we can use is to use the Heroku static buildpack's proxy backends feature.

To implement that would require a few steps.

Step 1: Remove the explicit domain references

Find all instances of https://murmuring-headland-63935.herokuapp.com/api/ in the frontend code and replace them with just /api/.

⚠️ Some extra step probably needs to be taken here to ensure that the local Vue frontend can connect with the local Express backend since they are currently hosted on different ports. Perhaps a Vue Router change or something? I'm not 100% certain on that works, e.g. https://medium.com/bb-tutorials-and-thoughts/vue-js-how-to-proxy-to-backend-server-a562bad965eb

Step 2: Add a backend proxy configuration to static.json

Using a Heroku config var reference like API_ORIGIN:

{
  "proxies": {
    "/api/": {
      "origin": "${API_ORIGIN}/api/"
    }
  }
}

Step 3: Create a Heroku config var for the frontend

API_ORIGIN=https://murmuring-headland-63935.herokuapp.com

Step 4: Deploy!

Now that everything is configured, we need to ensure our latest code with these changes is deployed to the staging frontend Heroku App! 🚀

Step 5: Verify and multiply

After confirming that this works as expected with the staging Heroku App:

  • Update the production Heroku App with the config var and redeploy it
  • Update the frontend ("hackathon"?) Heroku pipeline with the config var

Step 6: Create more backend environments (if desired)

This will allow us to create a staging environment for the backend code as well, and even a separate PostgreSQL database (probably a good idea to avoid messing up production data) -- if desired! The obvious gotcha to watch out for here would be the Heroku billing costs. 💰

Just remember to update the frontend config vars to point at your preferred backend URLs per environment. ↔️

Coupon Code: Stripe

User Story:

Coupon codes make it more accessible for people of all backgrounds to be able to participate in civic engagement. In our use case, an advocacy organization can give codes at their discretion via email, social media, or through in person.

Screen Shot 2022-02-22 at 4 45 18 PM

Within checkout.vue we have a space for a promo code. The use case here if that if a person enters a code in the input text box below and if its under the threshold of times discounted:

  1. If you didn't select a donation amount, your total will come out to zero
  2. If you plan on sending donation, your total will not include post cost of 1.00 ('donate and send' button appears)

We might want to also consider adding messaging if a limit has been reached or if the coupon code doesn't work

Implementation:

Stripe currently lays out the following for integrating coupons into checkout:

  1. Outreach teams adds coupons into dashboard

Screen Shot 2022-02-22 at 4 06 36 PM

We'll use 'amount off' which takes a dollar off
  1. It seems you can't apply a coupon directly to the redirectToCheckout method, you have to create a Checkout session first and then use that.

  2. Add a discount to Checkout the sample code is calling Checkout.session.create, not Checkout directly

Quick note
redirectToCheckout Reference Docs doesn't mention a discount or coupon parameter at all, and the sample code again is creating a Checkout session using fetch (to one's own server backend, which is where my expertise ceases and where I'm stifled), to generate a session ID and then passing that into the result where redirectToCheckout is called.

Questions:
Can coupons be done on just client side?
Does coupon exhaust the customizations we have access to?

Batch: Improve precommit lint/format checking

Our current git precommit hook only checks if our code linting and/or formatting has errors, but does not actually fix such errors when possible.

This is something that is definitely achievable.

Draft PR from the old backend repo: OpenSourceFellows/amplify-back-end#145

⚠️ ☝🏻 As you can read in that PR, there were some issues I ran into that prevented me from moving ahead with it at the itme, even though they may not truly be blockers. 🤷🏻‍♂️

Bug: createAddress not working

Expected Behaviour

We recently combined the addressVerification and createAddress as one api call. However, the new createAddress call does not seem to be working. I would expect createAddress api in lob.js to send me an address_id as a response if I send an address to it. @teakopp We were working on this in the hackathon but don't think we found the problem.

Current Behaviour

I keep receiving a "Something failed" error instead of an address_id. I have tried different variations of the address and ensured that the address is correct through addressVerification.

createAddress failing
Screen Shot 2022-02-25 at 3 04 06 PM

addressVerification working - shows its not an issue with the address
Screen Shot 2022-02-25 at 3 07 10 PM

Support use of Heroku Review Apps

@manishapriya94 recently enabled Heroku Review Apps (TL;DR: a separate deployed Heroku App per PR).

However, since it looks like the Apps cannot be configured [much] in the Heroku UI, I'm guessing that this repo will need to add an app.json manifest file to specify some critical pieces like which Heroku buildpacks need to be used.

e.g.

{
  "buildpacks": [
    {
      "url": "heroku/nodejs"
    },
    {
      "url": "https://github.com/heroku/heroku-buildpack-static"
    }
  ]
}

OpenAPI Workflow

Context

This issue describes the various steps needed to make and deploy changes to our OpenAPI description.

Modify
First, make your modifications to the OpenAPI description files.

Make sure your operations are assigned to their associated endpoint implementations.

Regenerate
Because not all operations are found in all releases, we have an additional build step that builds the OpenAPI roots (mainly paths and other top level metadata) based on x-github-releases and related release-specific changes

The OpenAPI root files are found at the root of app/api/description folder.

app/api/description/
├── api.github.com.yaml
├── ghes-2.18.yaml
├── ghes-2.19.yaml
├── ghes-2.20.yaml
├── ghes-2.21.yaml
├── github.ae.yaml
⚠️ These are the files used in tests so make sure these are up to date!

To update the root files, run:

$ ./bin/openapi generate-root-files
✅ Wrote 70148 bytes to app/api/description/ghes-3.0.yaml
✅ Wrote 71065 bytes to app/api/description/ghes-3.1.yaml
✅ Wrote 66196 bytes to app/api/description/ghes-2.22.yaml
✅ Wrote 50868 bytes to app/api/description/ghes-2.18.yaml
✅ Wrote 51514 bytes to app/api/description/ghes-2.19.yaml
✅ Wrote 51860 bytes to app/api/description/ghes-2.20.yaml
✅ Wrote 56220 bytes to app/api/description/ghes-2.21.yaml
✅ Wrote 78869 bytes to app/api/description/api.github.com.yaml
✅ Wrote 63453 bytes to app/api/description/github.ae.yaml
🎉 Root files updated! Please commit the resulting files.
Preview
To preview your changes on https://docs.github.com/, see Publishing REST API docs or reach out to #docs-apis-and-events for help.

Deploy
Once you’ve made your changes, you’ll have to deploy github/github and merge the default branch before the changes get reflected to docs and our open source descriptions. Thankfully, this amazing guide explains the process in detail. Feel free to reach out to #ecosystem-api for help.

Sync
Once github/github has been deployed and builds run on the default branch, a pull request will be automatically opened on github/rest-api-description and github/docs-internal by our friendly helper github-openapi-bot.

The github/rest-api-description PR must be merged to keep the open source OpenAPI description up to date.
The github/docs-internal PR must be merged to keep https://docs.github.com/ up-to-date.
For now, while we gain confidence, the PRs need to be merged manually by a human. Eventually, we hope to make this process will be fully automatic.

Epic 3: Document API with an OpenAPI schema

Description

Mission statement: Users can read the “raw” OpenAPI docs since they’re written in YAML, but for a better experience, we want to build a Pages site that intakes the raw files and outputs formatted, easy-to-read information.

Context
We currently document our API with manually updating Wiki pages, which are prone to inaccuracy and to becoming outdated. 😕

One alternative to consider would be documenting the API with a central OpenAPI schema file.

Side benefit: if desired, we can also then use additional Express middleware tooling for request validation. I have mixed feelings about this in practice based on past experiences but it is not unlikely that there are better tools available these days than a few years back. 🤷🏻‍♂️

With either of those approaches, we can then generate the documentation for it using the existing OpenAPI/Swagger tooling (see example demo page).

Spec

SMART exit criteria:

  • Specific – API documentation
  • Measurable – API-related PRs include schema changes rather than requiring manual updates to the documentation
  • Assignable – I'm open to it unless someone else would like to jump in
  • Realistic – auto-generated documentation based on developer-led API changes at the code/schema level
  • Time-related – Probably a week's worth of intermittent work

Links/Attachments for Reference

Considerations

  • Since our API is only callable by our own frontend, is this just creating unnecessary work for us in the long term?
    • Similar question for our Wiki-based documentation, though, to be honest? 🤷🏻‍♂️
    • I think given the nature of our project and how contributors may be transient, this could still be a valuable idea. 🤔

Exit Criteria Implementation notes

  • Create OpenAPI schema file and document the API in it
  • Add Actions workflow to generate Swagger UI documentation from the OpenAPI schema and store it into the gh-pages branch
  • Enable GitHub Pages to host the documentation from the gh-pages branch
  • Potentially add Express middleware for schema-based validation

Hack out Tasks (9:15-10:30):

Send Letter: Post Letter Object

User Story:

  • after user successfully finishes checkout of letter and any donation amounts, a send button appears
  • When user presses the button, backend creates a call to Lob with letter object

implementation:

  • check if user has successful payment with stripe
  • call lob api to create a letter object
  • accepts the token, verifies the address, creating a payment with Stripe, creates the letter if payment successful. Reroute if theres an error
  • Ensure frontend has variables to call with payment successful
  • send zipcode and email to Stripe checkout
  • #82

Screen Shot 2021-11-14 at 2 46 38 PM

check_payment: Boolean for Stripe Succesful payment:

  • set up a check to otherwise restrict call to create_letter discussion here

Screen Shot 2021-11-14 at 6 04 45 PM

create_letter function: Post Lob Letter API Call:

Context:

Epic: CI/CD Workflows

Use Case:

CI ensures all tests are built and executing when a pull request is opened:

What is CI/CD?
In the context of DevSecOps its the continuous integration and continuous deployment with each commit

Context of current CI/CD

  • Backend has
    • CI to run Integration tests for Google Civic API, Lob, and Auth0
    • Deploys to this url
  • Frontend
    • needs to establish CI
    • deploys to GitHub pages

Task: Get ESLint + Prettier working for Vue files

I've noticed that our ESLint and Prettier configuration don't seem to be including and/or achieving what I would've expected with our *.vue files. Guessing we are missing some Vue-specific configuration and/or plugins there. 🔍

Our current git precommit hook only checks if our code linting and/or formatting has errors, but does not actually fix such errors when possible.

This is something that is definitely achievable.

Draft PR from the old backend repo: OpenSourceFellows/amplify-back-end#145

⚠️ ☝🏻 As you can read in that PR, there were some issues I ran into that prevented me from moving ahead with it at the time, even though they may not truly be blockers. 🤷🏻‍♂️

Probably helpful: https://www.digitalocean.com/community/tutorials/vuejs-vue-eslint-prettier

Host frontend + backend code on a single port

Given our application's nature, we should ideally just host the frontend + backend code with one Express port (for both dev and production). This should simplify our onboarding for local development, our Codespaces configuration, and our deployment strategy.

In terms of deployment, we would only need a single self-contained Heroku App, and could even consider using other hosting services like Azure, AWS, GCP, etc. 🚀

While researching this, I found that it is easy enough to have an Express app host a built production Vue app but I struggled to find good resources on how to do it in a way that still supported hot-reloading of Vue from a development perspective.

The most interesting resource I found on the topic was this one, which seemed very promising in its unique approach of mounting the Express app into the Vue app (vue-cli-service app, that is) since it already has an internal Express server. 🔄

Related:

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.