Skip to content

Commit

Permalink
Release 2024.03.1 (#1929)
Browse files Browse the repository at this point in the history
  • Loading branch information
angela-tran committed Mar 1, 2024
2 parents e1aca40 + 251999c commit c32987e
Show file tree
Hide file tree
Showing 57 changed files with 1,584 additions and 864 deletions.
6 changes: 6 additions & 0 deletions .devcontainer/Dockerfile
@@ -1,5 +1,11 @@
FROM benefits_client:latest

# install Azure CLI
# https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?pivots=apt
USER root
RUN curl -sL https://aka.ms/InstallAzureCLIDeb | bash
USER $USER

# install devcontainer requirements
RUN pip install -e .[dev,test]

Expand Down
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Expand Up @@ -5,7 +5,7 @@
"service": "dev",
"runServices": ["dev", "docs", "server"],
"workspaceFolder": "/home/calitp/app",
"postStartCommand": ["/bin/bash", "bin/init.sh"],
"postStartCommand": ["/bin/bash", "bin/reset_db.sh"],
"postAttachCommand": ["/bin/bash", ".devcontainer/postAttach.sh"],
"customizations": {
"vscode": {
Expand Down
25 changes: 25 additions & 0 deletions .env.sample
@@ -0,0 +1,25 @@
DJANGO_SUPERUSER_USERNAME=benefits-admin
DJANGO_SUPERUSER_EMAIL=benefits-admin@calitp.org
DJANGO_SUPERUSER_PASSWORD=superuser12345!

DJANGO_DB_RESET=true
DJANGO_DB_DIR=.
DJANGO_DB_FILE=django.db
DJANGO_DB_FIXTURES="benefits/core/migrations/local_fixtures.json"

auth_provider_client_id=benefits-oauth-client-id
courtesy_card_verifier_api_auth_key=server-auth-token
mobility_pass_verifier_api_auth_key=server-auth-token
client_private_key='-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA1pt0ZoOuPEVPJJS+5r884zcjZLkZZ2GcPwr79XOLDbOi46on\nCa79kjRnhS0VUK96SwUPS0z9J5mDA5LSNL2RoxFb5QGaevnJY828NupzTNdUd0sY\nJK3kRjKUggHWuB55hwJcH/Dx7I3DNH4NL68UAlK+VjwJkfYPrhq/bl5z8ZiurvBa\n5C1mDxhFpcTZlCfxQoas7D1d+uPACF6mEMbQNd3RaIaSREO50NvNywXIIt/OmCiR\nqI7JtOcn4eyh1I4j9WtlbMhRJLfwPMAgY5epTsWcURmhVofF2wVoFbib3JGCfA7t\nz/gmP5YoEKnf/cumKmF3e9LrZb8zwm7bTHUViwIDAQABAoIBAQCIv0XMjNvZS9DC\nXoXGQtVpcxj6dXfaiDgnc7hZDubsNCr3JtT5NqgdIYdVNQUABNDIPNEiCkzFjuwM\nuuF2+dRzM/x6UCs/cSsCjXYBCCOwMwV/fjpEJQnwMQqwTLulVsXZYYeSUtXVBf/8\n0tVULRty34apLFhsyX30UtboXQdESfpmm5ZsqsZJlYljw+M7JxRMneQclI19y/ya\nhPWlfhLB9OffVEJXGaWx1NSYnKoCMKqE/+4krROr6V62xXaNyX6WtU6XiT7C6R5A\nPBxfhmoeFdVCF6a+Qq0v2fKThYoZnV4sn2q2An9YPfynFYnlgzdfnAFSejsqxQd0\nfxYLOtMBAoGBAP1jxjHDJngZ1N+ymw9MIpRgr3HeuMP5phiSTbY2tu9lPzQd+TMX\nfhr1bQh2Fd/vU0u7X0yPnTWtUrLlCdGnWPpXivx95GNGgUUIk2HStFdrRx+f2Qvk\nG8vtLgmSbjQ26UiHzxi9Wa0a41PWIA3TixkcFrS2X29Qc4yd6pVHmicfAoGBANjR\nZ8aaDkSKLkq5Nk1T7I0E1+mtPoH1tPV/FJClXjJrvfDuYHBeOyUpipZddnZuPGWA\nIW2tFIsMgJQtgpvgs52NFI7pQGJRUPK/fTG+Ycocxo78TkLr/RIj8Kj5brXsbZ9P\n3/WBX5GAISTSp1ab8xVgK/Tm07hGupKVqnY2lCAVAoGAIql0YjhE2ecGtLcU+Qm8\nLTnwpg4GjmBnNTNGSCfB7IuYEsQK489R49Qw3xhwM5rkdRajmbCHm+Eiz+/+4NwY\nkt5I1/NMu7vYUR40MwyEuPSm3Q+bvEGu/71pL8wFIUVlshNJ5CN60fA8qqo+5kVK\n4Ntzy7Kq6WpC9Dhh75vE3ZcCgYEAty99uXtxsJD6+aEwcvcENkUwUztPQ6ggAwci\nje9Z/cmwCj6s9mN3HzfQ4qgGrZsHpk4ycCK655xhilBFOIQJ3YRUKUaDYk4H0YDe\nOsf6gTP8wtQDH2GZSNlavLk5w7UFDYQD2b47y4fw+NaOEYvjPl0p5lmb6ebAPZb8\nFbKZRd0CgYBC1HTbA+zMEqDdY4MWJJLC6jZsjdxOGhzjrCtWcIWEGMDF7oDDEoix\nW3j2hwm4C6vaNkH9XX1dr5+q6gq8vJQdbYoExl22BGMiNbfI3+sLRk0zBYL//W6c\ntSREgR4EjosqQfbkceLJ2JT1wuNjInI0eR9H3cRugvlDTeWtbdJ5qA==\n-----END RSA PRIVATE KEY-----'
client_public_key='-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1pt0ZoOuPEVPJJS+5r88\n4zcjZLkZZ2GcPwr79XOLDbOi46onCa79kjRnhS0VUK96SwUPS0z9J5mDA5LSNL2R\noxFb5QGaevnJY828NupzTNdUd0sYJK3kRjKUggHWuB55hwJcH/Dx7I3DNH4NL68U\nAlK+VjwJkfYPrhq/bl5z8ZiurvBa5C1mDxhFpcTZlCfxQoas7D1d+uPACF6mEMbQ\nNd3RaIaSREO50NvNywXIIt/OmCiRqI7JtOcn4eyh1I4j9WtlbMhRJLfwPMAgY5ep\nTsWcURmhVofF2wVoFbib3JGCfA7tz/gmP5YoEKnf/cumKmF3e9LrZb8zwm7bTHUV\niwIDAQAB\n-----END PUBLIC KEY-----'
mst_payment_processor_client_cert='-----BEGIN CERTIFICATE-----\nPEM DATA\n-----END CERTIFICATE-----'
mst_payment_processor_client_cert_private_key='-----BEGIN RSA PRIVATE KEY-----\nPEM DATA\n-----END RSA PRIVATE KEY-----'
mst_payment_processor_client_cert_root_ca='-----BEGIN CERTIFICATE-----\nPEM DATA\n-----END CERTIFICATE-----'
sacrt_payment_processor_client_cert='-----BEGIN CERTIFICATE-----\nPEM DATA\n-----END CERTIFICATE-----'
sacrt_payment_processor_client_cert_private_key='-----BEGIN RSA PRIVATE KEY-----\nPEM DATA\n-----END RSA PRIVATE KEY-----'
sacrt_payment_processor_client_cert_root_ca='-----BEGIN CERTIFICATE-----\nPEM DATA\n-----END CERTIFICATE-----'
sbmtd_payment_processor_client_cert='-----BEGIN CERTIFICATE-----\nPEM DATA\n-----END CERTIFICATE-----'
sbmtd_payment_processor_client_cert_private_key='-----BEGIN RSA PRIVATE KEY-----\nPEM DATA\n-----END RSA PRIVATE KEY-----'
sbmtd_payment_processor_client_cert_root_ca='-----BEGIN CERTIFICATE-----\nPEM DATA\n-----END CERTIFICATE-----'

testsecret="Hello from the local environment!"
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Expand Up @@ -14,6 +14,15 @@ updates:
include: "scope"
labels:
- "dependencies"
- package-ecosystem: "pip"
directory: "/docs" # requirements.txt
schedule:
interval: "daily"
commit-message:
prefix: "chore"
include: "scope"
labels:
- "dependencies"
- package-ecosystem: "github-actions"
# Workflow files stored in the
# default location of `.github/workflows`
Expand Down
74 changes: 16 additions & 58 deletions .github/workflows/check-api.yml
Expand Up @@ -2,81 +2,39 @@ name: Check access to API

on:
workflow_dispatch:
inputs:
environment:
type: choice
description: Select the API environment
options: [all, prod, qa]
schedule:
- cron: "0 12 * * *"

jobs:
check-api:
runs-on: ubuntu-latest
env:
SHOULD_RUN: |
${{ github.event_name == 'schedule'
|| github.event.inputs.environment == 'all'
|| github.event.inputs.environment == matrix.name
}}
strategy:
fail-fast: false
matrix:
include:
- name: prod
cert: API_CHECK_PROD_CERT
key: API_CHECK_PROD_KEY
ca-cert: API_CHECK_PROD_CA_CERT
url: API_CHECK_PROD_URL
data: API_CHECK_PROD_DATA

- name: qa
cert: API_CHECK_QA_CERT
key: API_CHECK_QA_KEY
ca-cert: API_CHECK_QA_CA_CERT
url: API_CHECK_QA_URL
data: API_CHECK_QA_DATA

name: Check API endpoint (${{ matrix.name }})
participant: [mst, sacrt, sbmtd]
env: [qa, prod]
steps:
- name: Echo workflow run information
run: |
echo "Triggering event name: ${{ github.event_name }}, \
APIs to check: ${{ github.event.inputs.environment }}"
- uses: actions/checkout@v4
with:
repository: "cal-itp/littlepay"

- name: Decode cert files
if: contains(env.SHOULD_RUN, 'true')
- name: Install the littlepay library
run: |
mkdir $RUNNER_TEMP/${{ matrix.name }}
temp_dir=$RUNNER_TEMP/${{ matrix.name }}
cat > $temp_dir/cert.pem <<- EOM
${{ secrets[matrix.cert] }}
EOM
cat > $temp_dir/key.pem <<- EOM
${{ secrets[matrix.key] }}
EOM
python3 -m pip install --upgrade pip
pip install -e .
cat > $temp_dir/cacert.ca <<- EOM
${{ secrets[matrix.ca-cert] }}
- name: Create config file and set config
run: |
cat > config.yaml <<- EOM
${{ secrets.API_CHECK_CONFIG }}
EOM
littlepay config config.yaml
- name: Call API endpoint
if: contains(env.SHOULD_RUN, 'true')
- name: Run littlepay to get access token
run: |
temp_dir=$RUNNER_TEMP/${{ matrix.name }}
curl -i --url ${{ secrets[matrix.url] }} \
--header 'Accept: application/json' \
--header 'Content-type: application/json' \
--data '${{ secrets[matrix.data] }}' \
--cert $temp_dir/cert.pem \
--key $temp_dir/key.pem \
--cacert $temp_dir/cacert.ca > $temp_dir/payload.txt
test $(head -n 1 $temp_dir/payload.txt | grep -o 201)
littlepay switch env ${{ matrix.env }}
littlepay switch participant ${{ matrix.participant }}
# https://www.ravsam.in/blog/send-slack-notification-when-github-actions-fails/#using-notify-slack-action
- name: Report failure to Slack
if: always()
uses: ravsamhq/notify-slack-action@v2
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/mkdocs.yml
Expand Up @@ -59,8 +59,17 @@ jobs:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_PREVIEW_APP_SITE_ID }}

- name: Find existing comment
uses: peter-evans/find-comment@v3
id: find-comment
with:
issue-number: ${{ github.event.number }}
comment-author: "github-actions[bot]"
body-includes: "Preview url: https://"

- name: Add Netlify link PR comment
uses: actions/github-script@v7
if: steps.find-comment.outputs.comment-id == ''
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/tests-cypress.yml
Expand Up @@ -15,8 +15,9 @@ jobs:

- name: Start app
run: |
touch .env
docker compose up --detach client server
cp .env.sample .env
docker compose up --detach server
docker compose run --detach --service-ports client bin/test_start.sh
- name: Run Cypress tests
uses: cypress-io/github-action@v6
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tests-ui.yml
Expand Up @@ -18,11 +18,11 @@ jobs:

- name: Start app
run: |
touch .env
cp .env.sample .env
docker compose up --detach client
- name: Run Lighthouse tests for a11y
uses: treosh/lighthouse-ci-action@10.1.0
uses: treosh/lighthouse-ci-action@11.4.0
with:
urls: |
http://localhost:8000
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
@@ -1,5 +1,7 @@
*.db
*.env
*fixtures.json
!benefits/core/migrations/local_fixtures.json
*.mo
*.tfbackend
*.tmp
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Expand Up @@ -34,7 +34,7 @@ repos:
args: ["--maxkb=1500"]

- repo: https://github.com/psf/black
rev: 24.1.1
rev: 24.2.0
hooks:
- id: black
types:
Expand Down
53 changes: 39 additions & 14 deletions benefits/core/admin.py
Expand Up @@ -2,22 +2,47 @@
The core application: Admin interface configuration.
"""

import logging
import requests

from django.conf import settings
from django.contrib import admin
from . import models

logger = logging.getLogger(__name__)


GOOGLE_USER_INFO_URL = "https://www.googleapis.com/oauth2/v3/userinfo"


for model in [
models.EligibilityType,
models.EligibilityVerifier,
models.PaymentProcessor,
models.PemData,
models.TransitAgency,
]:
logger.debug(f"Register {model.__name__}")
admin.site.register(model)


if settings.ADMIN:
import logging
from django.contrib import admin
from . import models
def pre_login_user(user, request):
logger.debug(f"Running pre-login callback for user: {user.username}")
token = request.session.get("google_sso_access_token")
if token:
headers = {
"Authorization": f"Bearer {token}",
}

logger = logging.getLogger(__name__)
# Request Google user info to get name and email
response = requests.get(GOOGLE_USER_INFO_URL, headers=headers, timeout=settings.REQUESTS_TIMEOUT)
user_data = response.json()
logger.debug(f"Updating user data from Google for user with email: {user_data['email']}")

for model in [
models.EligibilityType,
models.EligibilityVerifier,
models.PaymentProcessor,
models.PemData,
models.TransitAgency,
]:
logger.debug(f"Register {model.__name__}")
admin.site.register(model)
user.first_name = user_data["given_name"]
user.last_name = user_data["family_name"]
user.username = user_data["email"]
user.email = user_data["email"]
user.save()
else:
logger.warning("google_sso_access_token not found in session.")
26 changes: 21 additions & 5 deletions benefits/core/migrations/0001_initial.py
@@ -1,10 +1,13 @@
# Generated by Django 4.2.4 on 2023-08-16 15:06
# Generated by Django 5.0.1 on 2024-02-06 18:09

from django.db import migrations, models
import benefits.core.models
import benefits.secrets
import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = []
Expand All @@ -17,7 +20,10 @@ class Migration(migrations.Migration):
("sign_out_button_template", models.TextField(null=True)),
("sign_out_link_template", models.TextField(null=True)),
("client_name", models.TextField()),
("client_id", models.TextField()),
(
"client_id_secret_name",
benefits.core.models.SecretNameField(max_length=127, validators=[benefits.secrets.SecretNameValidator()]),
),
("authority", models.TextField()),
("scope", models.TextField(null=True)),
("claim", models.TextField(null=True)),
Expand All @@ -41,7 +47,12 @@ class Migration(migrations.Migration):
("active", models.BooleanField(default=False)),
("api_url", models.TextField(null=True)),
("api_auth_header", models.TextField(null=True)),
("api_auth_key", models.TextField(null=True)),
(
"api_auth_key_secret_name",
benefits.core.models.SecretNameField(
max_length=127, null=True, validators=[benefits.secrets.SecretNameValidator()]
),
),
("jwe_cek_enc", models.TextField(null=True)),
("jwe_encryption_alg", models.TextField(null=True)),
("jws_signing_alg", models.TextField(null=True)),
Expand Down Expand Up @@ -80,8 +91,13 @@ class Migration(migrations.Migration):
fields=[
("id", models.AutoField(primary_key=True, serialize=False)),
("label", models.TextField()),
("text", models.TextField(null=True)),
("remote_url", models.TextField(null=True)),
(
"text_secret_name",
benefits.core.models.SecretNameField(
max_length=127, null=True, validators=[benefits.secrets.SecretNameValidator()]
),
),
],
),
migrations.CreateModel(
Expand Down

0 comments on commit c32987e

Please sign in to comment.