Skip to content

Commit

Permalink
fix: auto enable videos when recv metadata from s3
Browse files Browse the repository at this point in the history
* fix: auto enable videos when json data is fetched from s3, allow sysadmins

* fix: add migration to handle superadmin role, fix navbar + github deploy action
  • Loading branch information
PThorpe92 authored Nov 19, 2024
1 parent c2d5d1f commit 89c1449
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 84 deletions.
151 changes: 93 additions & 58 deletions .github/workflows/container_builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
count=$(git diff --name-only HEAD~1 | grep "^${path}" | wc -l)
changes+="${path}:${count},"
done
changes="${changes%,}"
echo "changes=${changes}" >> $GITHUB_OUTPUT
- name: Debug changes
Expand All @@ -39,10 +40,10 @@ jobs:
if: github.repository == 'UnlockedLabs/UnlockEdv2' || github.repository == 'PThorpe92/UnlockEdv2'
needs: setup-env
runs-on: ubuntu-latest
outputs:
deployments: ${{ steps.build-images.outputs.deployments }}
env:
CHANGES: ${{ needs.setup-env.outputs.changes }}
outputs:
deployments: ${{ steps.determine-deployments.outputs.deployments }}

steps:
- name: Checkout code
Expand All @@ -64,61 +65,95 @@ jobs:

- id: build-images
run: |
deployments=()
for entry in ${{ needs.setup-env.outputs.changes }}; do
path=$(echo $entry | cut -d':' -f1)
count=$(echo $entry | cut -d':' -f2)
if [[ $count -ne 0 ]]; then
case $path in
"frontend/")
echo "Building frontend image"
docker buildx build --platform linux/amd64 -t=${{ steps.login-ecr.outputs.registry }}/frontend:latest --push frontend/.
deployments+=("frontend")
;;
"backend/")
echo "Building backend image"
docker buildx build --platform linux/amd64 -t=${{ steps.login-ecr.outputs.registry }}/unlockedv2:latest --push -f backend/Dockerfile .
deployments+=("server")
;;
"provider-middleware/")
echo "Building middleware image"
docker buildx build --platform linux/amd64 -t=${{ steps.login-ecr.outputs.registry }}/provider_middleware:latest --push -f provider-middleware/Dockerfile .
deployments+=("provider-service")
;;
"backend/tasks")
echo "Building scheduler image"
docker buildx build --platform linux/amd64 -t=${{ steps.login-ecr.outputs.registry }}/cron_tasks:latest --push -f backend/tasks/Dockerfile .
deployments+=("cron-tasks")
;;
esac
fi
done
echo "deployments=${deployments[*]}" >> $GITHUB_OUTPUT
restart-deployments:
if: github.repository == 'UnlockedLabs/UnlockEdv2' || github.repository == 'PThorpe92/UnlockEdv2'
needs: build-and-push
runs-on: ubuntu-latest
env:
BASTION_HOST: ${{ secrets.BASTION_HOST }}
SSH_KEY: ${{ secrets.SSH_KEY }}

steps:
- name: Restart Deployments
run: |
deployments="${{ needs.build-and-push.outputs.deployments }}"
if [[ -z "$deployments" ]]; then
echo "No deployments need restarting."
exit 0
echo "CHANGES: $CHANGES"
deployments=()
IFS=',' read -ra entries <<< "$CHANGES"
for entry in "${entries[@]}"; do
if [ -z "$entry" ]; then
continue
fi
if [[ "${GITHUB_REF}" == "refs/heads/demo" ]]; then
CONTEXT="demo"
elif [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
CONTEXT="staging"
else
echo "Unknown branch: ${GITHUB_REF}. No deployments restarted."
exit 1
path=$(echo "$entry" | cut -d':' -f1)
count=$(echo "$entry" | cut -d':' -f2)
if [[ $count -ne 0 ]]; then
case $path in
"frontend/")
echo "Building frontend image"
docker buildx build --platform linux/amd64 -t=${{ steps.login-ecr.outputs.registry }}/frontend:latest --push frontend/.
deployments+=("frontend")
;;
"backend/")
echo "Building backend image"
docker buildx build --platform linux/amd64 -t=${{ steps.login-ecr.outputs.registry }}/unlockedv2:latest --push -f backend/Dockerfile .
deployments+=("server")
;;
"provider-middleware/")
echo "Building middleware image"
docker buildx build --platform linux/amd64 -t=${{ steps.login-ecr.outputs.registry }}/provider_middleware:latest --push -f provider-middleware/Dockerfile .
deployments+=("provider-service")
;;
"backend/tasks")
echo "Building scheduler image"
docker buildx build --platform linux/amd64 -t=${{ steps.login-ecr.outputs.registry }}/cron_tasks:latest --push -f backend/tasks/Dockerfile .
deployments+=("cron-tasks")
;;
esac
fi
ssh -i "$SSH_KEY" -o StrictHostKeyChecking=no "$BASTION_HOST" "bash -s" <<EOF
rollout.sh $CONTEXT $deployments
EOF
done
echo "deployments=${deployments[*]}" >> $GITHUB_OUTPUT
restart-deployments:
if: github.repository == 'UnlockedLabs/UnlockEdv2' || github.repository == 'PThorpe92/UnlockEdv2'
needs: build-and-push
runs-on: ubuntu-latest
env:
SECURITY_GROUP_ID: ${{ secrets.SECURITY_GROUP_ID }}
BASTION_HOST: ${{ secrets.BASTION_HOST }}
SSH_KEY: ${{ secrets.SSH_KEY }}

steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_IAM_ROLE }}
aws-region: us-west-2
mask-aws-account-id: true

- name: Get Runner Public IP
id: get_runner_ip
run: |
RUNNER_IP=$(curl -s https://checkip.amazonaws.com)
echo "Runner IP: $RUNNER_IP"
echo "RUNNER_IP=$RUNNER_IP" >> $GITHUB_ENV
- name: Add Runner IP to Security Group
run: |
echo "Adding runner IP $RUNNER_IP to security group $SECURITY_GROUP_ID"
aws ec2 authorize-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 22 --cidr ${RUNNER_IP}/32
- name: Restart Deployments
env:
RUNNER_IP: ${{ env.RUNNER_IP }}
run: |
deployments="${{ needs.build-and-push.outputs.deployments }}"
if [[ -z "$deployments" ]]; then
echo "No deployments need restarting."
exit 0
fi
if [[ "${GITHUB_REF}" == "refs/heads/demo" ]]; then
CONTEXT="demo"
elif [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
CONTEXT="staging"
else
echo "Unknown branch: ${GITHUB_REF}. No deployments restarted."
exit 1
fi
mkdir -p ~/.ssh && echo "$SSH_KEY" | base64 -d > ~/.ssh/id_rsa && chmod 400 ~/.ssh/id_rsa
ssh -i ~/.ssh/id_rsa -o StrictHostKeyChecking=no "$BASTION_HOST" "bash -s" <<EOF
rollout.sh $CONTEXT $deployments
EOF
- name: Remove Runner IP from Security Group
run: |
shred -u ~/.ssh/id_rsa || rm -f ~/.ssh/id_rsa
echo "Removing runner IP $RUNNER_IP from security group"
aws ec2 revoke-security-group-ingress --group-id $SECURITY_GROUP_ID --protocol tcp --port 22 --cidr ${RUNNER_IP}/32
File renamed without changes.
24 changes: 24 additions & 0 deletions backend/migrations/00019_set_superadmin_role_if_exists.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-- +goose Up
-- +goose StatementBegin
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM public.users WHERE id = 1 AND role = 'admin') THEN
UPDATE public.users
SET name = 'system_admin'
WHERE id = 1;
END IF;
END $$;
-- +goose StatementEnd


-- +goose Down
-- +goose StatementBegin
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM public.users WHERE id = 1 AND role = 'system_admin') THEN
UPDATE public.users
SET role = 'admin'
WHERE id = 1;
END IF;
END $$;
-- +goose StatementEnd
2 changes: 1 addition & 1 deletion backend/src/handlers/video_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func (srv *Server) handleGetVideoById(w http.ResponseWriter, r *http.Request, lo
if err != nil {
return newInternalServerServiceError(err, "error fetching video")
}
if user.Role != models.Admin && !video.VisibilityStatus || video.Availability != models.VideoAvailable {
if !user.isAdmin() && !video.VisibilityStatus || video.Availability != models.VideoAvailable {
return newForbiddenServiceError(errors.New("video not visible"), "you are not authorized to view this content")
}
return writeJsonResponse(w, http.StatusOK, video)
Expand Down
3 changes: 1 addition & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint-staged": "oxlint src && eslint --fix src",
"lint-staged": "eslint --fix src",
"lint": "eslint .",
"preview": "vite preview",
"prepare": "cd .. && husky frontend/.husky"
Expand All @@ -16,7 +16,6 @@
"axios": "^1.6.8",
"daisyui": "^4.10.5",
"eslint-plugin-prettier": "^5.2.1",
"oxlint": "^0.3.2",
"path": "^0.12.7",
"postcss": "^8.4.38",
"prettier": "^3.2.5",
Expand Down
23 changes: 10 additions & 13 deletions frontend/src/Components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,16 @@ import {
ChevronDoubleLeftIcon,
ChevronDoubleRightIcon,
HomeIcon,
RectangleStackIcon,
TrophyIcon,
UsersIcon,
ArrowRightEndOnRectangleIcon,
SunIcon,
MoonIcon,
UserCircleIcon,
DocumentTextIcon,
BuildingOffice2Icon
FolderOpenIcon,
CloudIcon,
RectangleStackIcon
} from '@heroicons/react/24/solid';
import { handleLogout, hasFeature, isAdministrator, useAuth } from '@/useAuth';
import ULIComponent from './ULIComponent';
Expand Down Expand Up @@ -118,17 +119,15 @@ export default function Navbar({
<li>
<Link to="/provider-platform-management">
<ULIComponent
icon={RectangleStackIcon}
icon={CloudIcon}
/>
Platforms
</Link>
</li>
<li className="">
<Link to="/course-catalog-admin">
<ULIComponent
icon={
BuildingStorefrontIcon
}
icon={FolderOpenIcon}
/>
Course Catalog
</Link>
Expand All @@ -151,11 +150,11 @@ export default function Navbar({
<li>
<Link to="/facilities-management">
<ULIComponent
icon={RectangleStackIcon}
icon={BuildingStorefrontIcon}
/>
Programs
Facilities
</Link>
</li> */}
</li>
</>
) : (
<>
Expand All @@ -174,17 +173,15 @@ export default function Navbar({
<li>
<Link to="/my-courses">
<ULIComponent
icon={BookOpenIcon}
icon={RectangleStackIcon}
/>{' '}
My Courses
</Link>
</li>
<li>
<Link to="/course-catalog">
<ULIComponent
icon={
BuildingStorefrontIcon
}
icon={FolderOpenIcon}
/>
Course Catalog
</Link>
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/Layouts/GuestLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Link } from 'react-router-dom';
import ApplicationLogo from '../Components/ApplicationLogo';
import { PropsWithChildren } from 'react';

export default function Guest({ children }: PropsWithChildren) {
return (
<div className="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-background">
<div>
<a href="/">
<Link to="/">
<ApplicationLogo className="w-20 h-20 fill-current text-slate-500" />
</a>
</Link>
</div>

<div className="w-full sm:max-w-md mt-6 px-6 py-4 bg-inner-background shadow-md overflow-hidden sm:rounded-lg">
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/Pages/StudentDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import convertSeconds from '@/Components/ConvertSeconds';
import ResourcesSideBar from '@/Components/ResourcesSideBar';
import WeekActivityChart from '@/Components/WeeklyActivity';
import Error from './Error';
import { useLoaderData, useNavigate } from 'react-router-dom';
import { Link, useLoaderData, useNavigate } from 'react-router-dom';
import {
AcademicCapIcon,
ArrowRightIcon,
Expand Down Expand Up @@ -54,13 +54,13 @@ export default function StudentDashboard() {
Looking for more content to engage with? Browse courses
offered at your facility.
</p>
<a
<Link
to="/course-catalog"
className="flex flex-row gap-1 body-small text-teal-3 mt-2"
onClick={() => navigate(`/course-catalog`)}
>
Explore courses
<ArrowRightIcon className="w-4" />
</a>
</Link>
</div>
</div>
);
Expand Down
12 changes: 8 additions & 4 deletions provider-middleware/video_dl.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (yt *VideoService) syncVideoMetadataFromS3(ctx context.Context) error {
logger().Errorf("error decoding video json: %v", err)
return
}
if _, _, err := yt.fetchAndSaveInitialVideoInfo(ctx, video.Url); err != nil {
if _, _, err := yt.fetchAndSaveInitialVideoInfo(ctx, video.Url, true); err != nil {
logger().Errorf("error fetching video info: %v", err)
}
}
Expand Down Expand Up @@ -339,7 +339,7 @@ func (yt *VideoService) addVideos(ctx context.Context) error {
if videoExists {
return
}
result, vid, err := yt.fetchAndSaveInitialVideoInfo(ctx, url)
result, vid, err := yt.fetchAndSaveInitialVideoInfo(ctx, url, false)
if err != nil {
logger().Errorf("Error fetching video info: %v", err)
return
Expand Down Expand Up @@ -382,7 +382,7 @@ func (yt *VideoService) incrementFailedAttempt(ctx context.Context, vid *models.
return yt.db.WithContext(ctx).Create(&attempt).Error
}

func (yt *VideoService) fetchAndSaveInitialVideoInfo(ctx context.Context, vidUrl string) (*goutubedl.Result, *models.Video, error) {
func (yt *VideoService) fetchAndSaveInitialVideoInfo(ctx context.Context, vidUrl string, avail bool) (*goutubedl.Result, *models.Video, error) {
result, err := goutubedl.New(ctx, vidUrl, goutubedl.Options{
Type: goutubedl.TypeAny,
DebugLog: logger(),
Expand All @@ -400,14 +400,18 @@ func (yt *VideoService) fetchAndSaveInitialVideoInfo(ctx context.Context, vidUrl
Title: result.Info.Title,
Description: stripUrlsFromDescription(result.Info.Description),
ChannelTitle: &result.Info.Channel,
Availability: models.VideoProcessing,
YoutubeID: result.Info.ID,
VisibilityStatus: false,
Url: vidUrl,
ThumbnailUrl: thumbnail,
Duration: int(result.Info.Duration),
OpenContentProviderID: yt.OpenContentProviderID,
}
if avail {
vid.Availability = models.VideoAvailable
} else {
vid.Availability = models.VideoProcessing
}
if err := yt.db.WithContext(ctx).Create(vid).Error; err != nil {
logger().Errorln(err)
return nil, nil, err
Expand Down

0 comments on commit 89c1449

Please sign in to comment.