Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,7 @@ jobs:
gh workflow run deploy.yml \
--ref develop \
-f version_type=latest \
-f environment=dev \
-f run_legacy_cluster_tests=true
-f environment=dev

echo "Triggered deploy workflow for dev environment with latest containers"
echo "View workflow runs: https://github.com/${{ github.repository }}/actions/workflows/deploy.yml"
115 changes: 1 addition & 114 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ on:
options:
- dev
- prod
run_legacy_cluster_tests:
description: 'Run cluster tests for frontend-legacy before deploying'
required: true
type: boolean
default: true
workflow_call:
inputs:
version_type:
Expand All @@ -46,11 +41,6 @@ on:
required: false
type: string
default: prod
run_legacy_cluster_tests:
description: "Run cluster tests for frontend-legacy before deploying"
required: false
type: boolean
default: true

permissions:
contents: read
Expand Down Expand Up @@ -83,105 +73,9 @@ jobs:
repo: platform
specific-version: ${{ inputs.version_type != 'latest' && inputs.specific_version || '' }}

test-release:
name: Test Release
needs: [determine-version]
if: ${{ inputs.run_legacy_cluster_tests == true || inputs.run_legacy_cluster_tests == 'true' }}
runs-on: ubuntu-latest

env:
FORCE_COLOR: 1
PYTHONUNBUFFERED: 1
PYTHONDONTWRITEBYTECODE: 1
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
PLATFORM_EMAIL_HOST_USER: ${{ secrets.PLATFORM_EMAIL_HOST_USER }}
PLATFORM_EMAIL_HOST_PASSWORD: ${{ secrets.PLATFORM_EMAIL_HOST_PASSWORD }}
PLATFORM_TWILIO_ACCOUNT_SID: ${{ secrets.PLATFORM_TWILIO_ACCOUNT_SID }}
PLATFORM_TWILIO_AUTH_TOKEN: ${{ secrets.PLATFORM_TWILIO_AUTH_TOKEN }}
PLATFORM_TWILIO_SMS_FROM: ${{ vars.PLATFORM_TWILIO_SMS_FROM }}
AWS_INTEGRATION_S3_ACCESS_KEY_ID: ${{ secrets.AWS_INTEGRATION_S3_ACCESS_KEY_ID }}
AWS_INTEGRATION_S3_SECRET_ACCESS_KEY: ${{ secrets.AWS_INTEGRATION_S3_SECRET_ACCESS_KEY }}
CI_TWILIO_RECIPIENT_PHONE_NUMBER: ${{ secrets.CI_TWILIO_RECIPIENT_PHONE_NUMBER }}

steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v3
with:
client-id: ${{ secrets.HELIUM_BOT_APP_ID }}
private-key: ${{ secrets.HELIUM_BOT_PRIVATE_KEY }}
skip-token-revoke: true

- name: Checkout infra monorepo
uses: actions/checkout@v6
with:
repository: HeliumEdu/infra
token: ${{ steps.app-token.outputs.token }}
path: deploy

- name: Set up Python "3.12"
uses: actions/setup-python@v6
with:
python-version: "3.12"

- name: Install GitHub SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_KEY_GITHUB }}
known_hosts: ${{ secrets.KNOWN_HOSTS_GITHUB }}
if_key_exists: replace

- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Checkout platform repository
uses: actions/checkout@v6
with:
repository: HeliumEdu/platform
ref: ${{ needs.determine-version.outputs.version }}
path: platform-repo

- name: Set container environment variables
env:
VERSION_NUMBER: ${{ needs.determine-version.outputs.version_number }}
run: |
echo "PLATFORM_RESOURCE_IMAGE=public.ecr.aws/heliumedu/helium/platform-resource:amd64-${VERSION_NUMBER}" >> $GITHUB_ENV
echo "PLATFORM_API_IMAGE=public.ecr.aws/heliumedu/helium/platform-api:amd64-${VERSION_NUMBER}" >> $GITHUB_ENV
echo "PLATFORM_WORKER_IMAGE=public.ecr.aws/heliumedu/helium/platform-worker:amd64-${VERSION_NUMBER}" >> $GITHUB_ENV
: ${FRONTEND_LEGACY_VERSION:=latest}
echo "FRONTEND_LEGACY_VERSION=${FRONTEND_LEGACY_VERSION}" >> $GITHUB_ENV
echo "FRONTEND_IMAGE=public.ecr.aws/heliumedu/helium/frontend:legacy-amd64-${FRONTEND_LEGACY_VERSION}" >> $GITHUB_ENV

- name: Install dependencies
working-directory: deploy
run: make install

- name: Run cluster tests for frontend-legacy against release build
working-directory: deploy
env:
TAG_VERSION: ${{ needs.determine-version.outputs.version }}
run: make test-cluster-legacy

- name: Upload test output
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
name: cluster-test-output-${{ needs.determine-version.outputs.version }}
path: deploy/projects/cluster-tests/build/screenshots/
retention-days: 30

- name: Dump Docker logs on failure
if: failure()
uses: jwalton/gh-docker-logs@v2

deploy:
name: Deploy to ${{ inputs.environment }}
needs: [determine-version, test-release]
if: "!cancelled() && needs.determine-version.result == 'success' && (needs.test-release.result == 'success' || needs.test-release.result == 'skipped')"
needs: [determine-version]
runs-on: ubuntu-latest

env:
Expand Down Expand Up @@ -266,13 +160,6 @@ jobs:
pip install sentry-cli
SENTRY_PROPERTIES=sentry.properties sentry-cli releases deploys "$RELEASE_VERSION" new --env "${{ inputs.environment }}"

- name: Trigger legacy cluster-tests run
run: |
curl -s -X POST https://api.github.com/repos/HeliumEdu/cluster-tests/dispatches \
-H "Authorization: token ${{ steps.app-token.outputs.token }}" \
-H "Accept: application/vnd.github+json" \
-d "{\"event_type\":\"\`platform\` triggered for \`${{ needs.determine-version.outputs.version }}\` to \`${{ inputs.environment }}\`\",\"client_payload\":{\"environment\":\"${{ inputs.environment }}\",\"project\":\"platform\",\"version\":\"${{ needs.determine-version.outputs.version }}\"}}"

- name: Trigger frontend integration tests
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
Expand Down
16 changes: 1 addition & 15 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,6 @@ on:
options:
- dev
- prod
run_legacy_cluster_tests:
description: 'Run cluster tests for frontend-legacy before deploying'
required: true
type: boolean
default: true
workflow_call:
inputs:
bump_type:
Expand All @@ -49,11 +44,6 @@ on:
required: false
type: string
default: prod
run_legacy_cluster_tests:
description: "Run cluster tests for frontend-legacy before deploying"
required: false
type: boolean
default: true
outputs:
version:
description: "Released version"
Expand Down Expand Up @@ -251,26 +241,22 @@ jobs:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
VERSION: ${{ needs.prereq.outputs.version }}
ENVIRONMENT: ${{ inputs.environment }}
RUN_LEGACY_CLUSTER_TESTS: ${{ inputs.run_legacy_cluster_tests }}
run: |
gh workflow run deploy.yml \
--repo ${{ github.repository }} \
-f version_type=specific \
-f specific_version="$VERSION" \
-f environment="$ENVIRONMENT" \
-f run_legacy_cluster_tests="$RUN_LEGACY_CLUSTER_TESTS"
-f environment="$ENVIRONMENT"

- name: Deployment trigger summary
env:
VERSION: ${{ needs.prereq.outputs.version }}
ENVIRONMENT: ${{ inputs.environment }}
RUN_LEGACY_CLUSTER_TESTS: ${{ inputs.run_legacy_cluster_tests }}
run: |
echo "### Deploy Workflow Triggered" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Version**: $VERSION" >> $GITHUB_STEP_SUMMARY
echo "- **Environment**: $ENVIRONMENT" >> $GITHUB_STEP_SUMMARY
echo "- **Run Legacy Cluster Tests**: $RUN_LEGACY_CLUSTER_TESTS" >> $GITHUB_STEP_SUMMARY

cleanup:
needs: [prereq, deploy]
Expand Down
31 changes: 4 additions & 27 deletions conf/configs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,16 @@

PROJECT_APP_HOST = config('PROJECT_FLUTTER_APP_HOST', 'http://localhost:8080' if 'local' in ENVIRONMENT else f'https://app.{ENVIRONMENT_PREFIX}heliumedu.com')
PROJECT_API_HOST = config('PROJECT_API_HOST', 'http://localhost:8000' if 'local' in ENVIRONMENT else f'https://api.{ENVIRONMENT_PREFIX}heliumedu.com')
PROJECT_APP_LEGACY_HOST = config('PROJECT_APP_HOST', 'http://localhost:3000' if 'local' in ENVIRONMENT else f'https://www.{ENVIRONMENT_PREFIX}heliumedu.com')

# Version information

PROJECT_VERSION = __version__

FRONTEND_LEGACY_VERSION = config('PLATFORM_FRONTEND_LEGACY_VERSION', "latest")

# AWS S3

AWS_S3_ACCESS_KEY_ID = config('PLATFORM_AWS_S3_ACCESS_KEY_ID')
AWS_S3_SECRET_ACCESS_KEY = config('PLATFORM_AWS_S3_SECRET_ACCESS_KEY')

# Twilio

TWILIO_ACCOUNT_SID = config('PLATFORM_TWILIO_ACCOUNT_SID')
TWILIO_AUTH_TOKEN = config('PLATFORM_TWILIO_AUTH_TOKEN')
TWILIO_SMS_FROM = config('PLATFORM_TWILIO_SMS_FROM')

# Google Analytics

GA4_MEASUREMENT_ID = config('PLATFORM_GA4_MEASUREMENT_ID', default=None)
Expand Down Expand Up @@ -243,12 +234,11 @@
),
'DEFAULT_THROTTLE_CLASSES': (
'rest_framework.throttling.AnonRateThrottle',
'helium.common.throttles.UserRateThrottle',
'rest_framework.throttling.UserRateThrottle',
),
'DEFAULT_THROTTLE_RATES': {
'anon': '10/min',
'user': '120/min',
'user_legacy': '300/min', # TODO: Remove once the legacy frontend (www.heliumedu.com) is retired
'user_token': '5/hour',
'delete_inactive': '1/min',
'support_contact': '5/hour',
Expand All @@ -260,10 +250,6 @@
ACCESS_TOKEN_TTL_MINUTES = 5
REFRESH_TOKEN_TTL_DAYS = 14

# TTL values for the legacy frontend that doesn't reliably support token refresh
LEGACY_ACCESS_TOKEN_TTL_MINUTES = 60 * 24 * 7
LEGACY_REFRESH_TOKEN_TTL_DAYS = int(config('PLATFORM_LEGACY_REFRESH_TOKEN_TTL_DAYS', '30'))

if ACCESS_TOKEN_TTL_MINUTES < 3:
raise ImproperlyConfigured("ACCESS_TOKEN_TTL_MINUTES cannot be less than 3")

Expand Down Expand Up @@ -494,7 +480,6 @@
# Email settings

DISABLE_EMAILS = config('PROJECT_DISABLE_EMAILS', 'False') == 'True'
DISABLE_TEXTS = config('PROJECT_DISABLE_TEXTS', 'False') == 'True'
DISABLE_PUSH = config('PROJECT_DISABLE_PUSH', 'False') == 'True'

REMINDER_SEND_WINDOW_MINUTES = int(config('PROJECT_REMINDER_SEND_WINDOW_MINUTES', '15'))
Expand Down Expand Up @@ -568,22 +553,20 @@

PROJECT_LANDING_HOST = config(
'PROJECT_LANDING_HOST',
'http://localhost:4321' if 'local' in ENVIRONMENT else f'https://landing.{ENVIRONMENT_PREFIX}heliumedu.com'
'http://localhost:4321' if 'local' in ENVIRONMENT else f'https://www.{ENVIRONMENT_PREFIX}heliumedu.com'
)

CSRF_TRUSTED_ORIGINS = [
PROJECT_APP_HOST,
PROJECT_API_HOST,
PROJECT_APP_LEGACY_HOST,
strip_www(PROJECT_APP_LEGACY_HOST),
PROJECT_LANDING_HOST,
strip_www(PROJECT_LANDING_HOST),
]
CORS_ALLOWED_ORIGINS = [
PROJECT_APP_HOST,
PROJECT_API_HOST,
PROJECT_APP_LEGACY_HOST,
strip_www(PROJECT_APP_LEGACY_HOST),
PROJECT_LANDING_HOST,
strip_www(PROJECT_LANDING_HOST),
]

if PROJECT_CI_APP_HOST:
Expand All @@ -605,16 +588,10 @@
CSRF_TRUSTED_ORIGINS += [
'http://localhost:8080',
'http://127.0.0.1:8080',
# Legacy frontend
'http://localhost:3000',
'http://127.0.0.1:3000',
]
CORS_ALLOWED_ORIGINS += [
'http://localhost:8080',
'http://127.0.0.1:8080',
# Legacy frontend
'http://localhost:3000',
'http://127.0.0.1:3000',
]

if 'local' in ENVIRONMENT:
Expand Down
43 changes: 2 additions & 41 deletions helium/auth/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from rest_framework_simplejwt.token_blacklist.admin import OutstandingTokenAdmin, BlacklistedTokenAdmin
from rest_framework_simplejwt.token_blacklist.models import OutstandingToken, BlacklistedToken

from helium.auth.models import UserProfile
from helium.auth.models import UserSettings
from helium.auth.models.tokenproxy import BlacklistedTokenProxy, OutstandingTokenProxy
from helium.auth.models.userclientactivity import UserClientActivity
Expand Down Expand Up @@ -334,7 +333,7 @@ class UserAdmin(ObjectActionsMixin, admin.UserAdmin, BaseModelAdmin):

list_display = ('email', 'last_activity', 'get_auth_type',
'num_notes', 'num_courses', 'num_homework', 'num_events',
'num_attachments', 'num_external_calendars', 'last_login_legacy',
'num_attachments', 'num_external_calendars',
'deletion_warning_count', 'deletion_requested_at', 'mobile_app_usage_percent_30d',
'created_at', 'is_active')
list_filter = (ActiveStatusFilter, PendingDeletionFilter, 'settings__show_getting_started',
Expand Down Expand Up @@ -396,7 +395,7 @@ def _user_count_subquery(model, user_path='user'):

def get_readonly_fields(self, request, obj=None):
if obj:
base = self.readonly_fields + ('created_at', 'last_login', 'last_login_legacy', 'last_activity',
base = self.readonly_fields + ('created_at', 'last_login', 'last_activity',
'mobile_app_usage_percent_30d', 'deletion_warning_count',
'deletion_warning_sent_at', 'onboarding_completed_at',
'deletion_requested_at', 'get_2fa_enabled',
Expand Down Expand Up @@ -471,43 +470,6 @@ def num_external_calendars(self, obj):
num_external_calendars.admin_order_field = '_num_external_calendars'


class UserProfileAdmin(BaseModelAdmin):
list_display = ['get_user', 'phone', 'phone_verified', 'get_last_login', 'get_last_activity']
list_filter = [staff_filter('user')]
search_fields = ('user__id', 'user__email', 'user__username')
ordering = ('-user__last_activity',)
readonly_fields = ('user', 'phone_changing', 'phone_verification_code', 'phone_verified',)

def has_add_permission(self, request):
return False

def has_delete_permission(self, request, obj=None):
return False

def get_user(self, obj):
if obj.user:
return obj.user.get_username()
else:
return ''

def get_last_login(self, obj):
if obj.user:
return obj.user.last_login
else:
return ''

def get_last_activity(self, obj):
if obj.user:
return obj.user.last_activity
else:
return ''

get_user.short_description = 'User'
get_user.admin_order_field = 'user__username'
get_last_login.short_description = 'Last Login'
get_last_login.admin_order_field = 'user__last_login'


class UserSettingsAdmin(BaseModelAdmin):
list_display = ['get_user', 'time_zone', 'default_view', 'default_reminder_type', 'color_scheme_theme',
'review_prompts_requested', 'get_last_activity']
Expand Down Expand Up @@ -666,7 +628,6 @@ def has_delete_permission(self, request, obj=None):

# Register the models in the Admin
admin_site.register(get_user_model(), UserAdmin)
admin_site.register(UserProfile, UserProfileAdmin)
admin_site.register(UserSettings, UserSettingsAdmin)
admin_site.register(UserPushToken, UserPushTokenAdmin)
admin_site.register(UserOAuthProvider, UserOAuthProviderAdmin)
Expand Down
Loading
Loading