Skip to content

Commit

Permalink
Merge branch 'Simon-Initiative:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
dtiwarATS authored Jul 25, 2024
2 parents cb29dba + 946e4d4 commit 15e26ab
Show file tree
Hide file tree
Showing 64 changed files with 926 additions and 529 deletions.
62 changes: 62 additions & 0 deletions .github/workflows/auto-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Auto Deploy

on:
# Run this workflow after the Package workflow completes
workflow_run:
workflows: [Package]
types: [completed]

jobs:
check-auto-deploy:
name: Check AUTO_DEPLOY_ENABLED config
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
environment:
name: ${{ vars.AUTO_DEPLOY_TARGET }}
url: https://${{ vars.AUTO_DEPLOY_TARGET }}
outputs:
enabled: ${{ steps.check_auto_deploy_enabled.outputs.enabled }}
auto_deploy_ref: ${{ steps.get_auto_deploy_ref.outputs.auto_deploy_ref }}
steps:
- name: Check whether AUTO_DEPLOY_ENABLED is set to TRUE
id: check_auto_deploy_enabled
run: echo "enabled=$(if [ "${{ vars.AUTO_DEPLOY_ENABLED }}" == "TRUE" ] ; then echo true ; else echo false ; fi)" >> $GITHUB_OUTPUT
- name: Get AUTO_DEPLOY_REF config
id: get_auto_deploy_ref
run: echo "auto_deploy_ref=$(if [ -n "${{ vars.AUTO_DEPLOY_REF }}" ] ; then echo ${{ vars.AUTO_DEPLOY_REF }} ; else echo refs/heads/master ; fi)" >> $GITHUB_OUTPUT

auto-deploy:
name: Auto Deploy
if: github.event.workflow_run.conclusion == 'success' && github.ref == needs.check-auto-deploy.outputs.auto_deploy_ref && needs.check-auto-deploy.outputs.enabled == 'true'
runs-on: ubuntu-latest
environment:
name: ${{ vars.AUTO_DEPLOY_TARGET }}
url: https://${{ vars.AUTO_DEPLOY_TARGET }}
needs: [check-auto-deploy]

steps:
- run: echo "Auto deploy enabled for ref ${{ vars.AUTO_DEPLOY_REF }}. Deploying ${{ github.sha }} ${{ github.ref }} ${{ github.ref_name }} to ${{ vars.AUTO_DEPLOY_TARGET }}"

# checkout the commit from the Package workflow that triggered the Auto Deploy workflow
- name: 🛎️ Checkout
uses: actions/checkout@v2
with:
ref: ${{ github.event.workflow_run.head_sha }}

- name: 🧾 Build info
id: info
run: |
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
echo "app_version=$(cat mix.exs | grep version | sed -e 's/.*version: "\(.*\)",/\1/')" >> $GITHUB_OUTPUT
echo "workspace=$GITHUB_WORKSPACE" >> $GITHUB_OUTPUT
- name: 🚢💰 Deploy to test using SSH
uses: fifsky/ssh-action@master
with:
command: |
cd /torus
sh deploy.sh -r ${{ github.ref }} ${{ steps.info.outputs.app_version }} ${{ steps.info.outputs.sha_short }}
host: ${{ vars.AUTO_DEPLOY_TARGET }}
user: simon-bot
key: ${{ secrets.SIMON_BOT_PRIVATE_KEY}}
port: 44067
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ on:
deploy_target:
description: "Deploy Target"
required: true
default: "tokamak.oli.cmu.edu"
type: choice
options:
- tokamak.oli.cmu.edu
Expand All @@ -27,6 +26,7 @@ on:
jobs:
deployment:
runs-on: ubuntu-latest
if: -n "${{github.event.inputs.deploy_target}}"

environment:
name: ${{ github.event.inputs.deploy_target }}
Expand Down
35 changes: 0 additions & 35 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,38 +119,3 @@ jobs:
SHA_SHORT=${{ steps.info.outputs.sha_short }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

check-auto-deploy:
name: Check AUTO_DEPLOY_ENABLED config
runs-on: ubuntu-latest
environment: tokamak.oli.cmu.edu
outputs:
enabled: ${{ steps.check_auto_deploy_enabled.outputs.enabled }}
auto_deploy_ref: ${{ steps.get_auto_deploy_ref.outputs.auto_deploy_ref }}
steps:
- name: Check whether AUTO_DEPLOY_ENABLED is set to TRUE
id: check_auto_deploy_enabled
run: echo "enabled=$(if [ "${{ vars.AUTO_DEPLOY_ENABLED }}" == "TRUE" ] ; then echo true ; else echo false ; fi)" >> $GITHUB_OUTPUT
- name: Get AUTO_DEPLOY_REF config
id: get_auto_deploy_ref
run: echo "auto_deploy_ref=$(if [ -n "${{ vars.AUTO_DEPLOY_REF }}" ] ; then echo ${{ vars.AUTO_DEPLOY_REF }} ; else echo refs/heads/master ; fi)" >> $GITHUB_OUTPUT

deployment:
runs-on: ubuntu-latest
environment: tokamak.oli.cmu.edu
needs: [amazon-linux, check-auto-deploy]
if: github.ref == needs.check-auto-deploy.outputs.auto_deploy_ref && needs.check-auto-deploy.outputs.enabled == 'true'

steps:
- run: echo "deploying ${{ github.sha }} ${{ github.ref }} ${{ github.ref_name }} to tokamak.oli.cmu.edu"

- name: 🚢💰 Deploy to test using SSH
uses: fifsky/ssh-action@master
with:
command: |
cd /torus
sh deploy.sh -r ${{ github.ref }} ${{ needs.amazon-linux.outputs.app_version }} ${{ needs.amazon-linux.outputs.sha_short }}
host: tokamak.oli.cmu.edu
user: simon-bot
key: ${{ secrets.SIMON_BOT_PRIVATE_KEY}}
port: 44067
1 change: 1 addition & 0 deletions assets/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,7 @@ module.exports = (env, options) => ({
'[email protected]': 'MIT',
'[email protected]': 'MIT',
'[email protected]': 'MIT',
'[email protected]': 'MIT',
'[email protected]': 'MIT',
},
unacceptableLicenseTest: (licenseIdentifier) => {
Expand Down
52 changes: 42 additions & 10 deletions lib/oli/accounts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -912,25 +912,33 @@ defmodule Oli.Accounts do
end

@doc """
Inserts or updates a user logged in via sso, and adds the user as a member of the given community.
Inserts or updates a user logged in via SSO, and adds the user as a member of the given community.
If `opts` includes `link_author: true`, an author is created and linked with the user.
## Examples
iex> setup_sso_user(fields, community_id)
{:ok, %User{}} -> # Inserted or updated with success
{:error, changeset} -> # Something went wrong
iex> setup_sso_user(fields, community_id, [])
{:ok, %User{}, nil} # Inserted or updated successfully, no author linked
iex> setup_sso_user(fields, community_id, [link_author: true])
{:ok, %User{}, %Author{}} # Inserted or updated successfully, author linked
iex> setup_sso_user(fields, community_id, [])
{:error, changeset} # Something went wrong
"""
def setup_sso_user(fields, community_id) do
def setup_sso_user(fields, community_id, opts \\ []) do
res =
Multi.new()
|> Multi.run(:user, &create_sso_user(&1, &2, fields))
|> Multi.run(:community_account, &create_community_account(&1, &2, community_id))
|> Multi.run(:author, &maybe_invite_author(&1, &2, fields, opts))
|> Multi.run(:linked_user, &link_user_with_author(&1, &2))
|> Repo.transaction()

case res do
{:ok, %{user: user}} ->
{:ok, user}
{:ok, %{user: user, author: author}} ->
{:ok, user, author}

{:error, _, changeset, _} ->
{:error, changeset}
Expand Down Expand Up @@ -962,11 +970,35 @@ defmodule Oli.Accounts do
end
end

defp link_user_with_author(_repo, %{user: user, author: author}) do
link_user_author_account(user, author)
end
defp link_user_with_author(_repo, %{user: user, author: nil}), do: {:ok, user}

defp link_user_with_author(_repo, %{user: user, author: author}),
do: link_user_author_account(user, author)

defp create_community_account(_repo, %{user: %User{id: user_id}}, community_id) do
Groups.find_or_create_community_user_account(user_id, community_id)
end

defp maybe_invite_author(_repo, %{user: user}, fields, opts) do
if Keyword.get(opts, :link_author, false) do
get_or_invite_author(user.email, fields)
else
{:ok, nil}
end
end

defp get_or_invite_author(email, fields) do
case get_author_by_email(email) do
nil ->
email = Map.get(fields, "email")
username = Map.get(fields, "cognito:username")

%Author{}
|> Author.invite_changeset(nil, %{name: username, email: email})
|> Repo.insert()

author ->
{:ok, author}
end
end
end
12 changes: 11 additions & 1 deletion lib/oli/accounts/schemas/author.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Oli.Accounts.Author do
use Ecto.Schema

use Pow.Ecto.Schema,
password_hash_methods: {&Bcrypt.hash_pwd_salt/1, &Bcrypt.verify_pass/2}
password_hash_verify: {&Bcrypt.hash_pwd_salt/1, &Bcrypt.verify_pass/2}

use PowAssent.Ecto.Schema

Expand All @@ -12,6 +12,9 @@ defmodule Oli.Accounts.Author do
import Ecto.Changeset
import Oli.Utils

import PowInvitation.Ecto.Schema,
only: [invitation_token_changeset: 1]

alias Oli.Accounts.SystemRole

schema "authors" do
Expand Down Expand Up @@ -111,6 +114,13 @@ defmodule Oli.Accounts.Author do
|> pow_assent_user_identity_changeset(user_identity, attrs, user_id_attrs)
end

@spec invite_changeset(Author.t() | Ecto.Changeset.t(), integer(), map()) :: Ecto.Changeset.t()
def invite_changeset(user_or_changeset, nil, attrs) do
user_or_changeset
|> Ecto.Changeset.cast(attrs, [:name, :email, :invitation_token, :given_name, :family_name])
|> invitation_token_changeset()
end

def invite_changeset(user_or_changeset, invited_by, attrs) do
user_or_changeset
|> Ecto.Changeset.cast(attrs, [:name, :given_name, :family_name])
Expand Down
2 changes: 1 addition & 1 deletion lib/oli/accounts/schemas/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Oli.Accounts.User do
use Ecto.Schema

use Pow.Ecto.Schema,
password_hash_methods: {&Bcrypt.hash_pwd_salt/1, &Bcrypt.verify_pass/2}
password_hash_verify: {&Bcrypt.hash_pwd_salt/1, &Bcrypt.verify_pass/2}

use PowAssent.Ecto.Schema

Expand Down
8 changes: 8 additions & 0 deletions lib/oli/email.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ defmodule Oli.Email do
|> html_text_body()
end

def invitation_email(recipient_email, :infiniscope_invitation, assigns) do
base_email()
|> to(recipient_email)
|> subject("Create Course Author Password")
|> render(:infiniscope_invitation, assigns)
|> html_text_body()
end

def invitation_email(recipient_email, view, assigns) do
base_email()
|> to(recipient_email)
Expand Down
1 change: 0 additions & 1 deletion lib/oli_web/components/delivery/instructor_dashboard.ex
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,6 @@ defmodule OliWeb.Components.Delivery.InstructorDashboard do

def section_details_header(%{section: nil} = assigns) do
~H"""
"""
end

Expand Down
1 change: 0 additions & 1 deletion lib/oli_web/components/delivery/student.ex
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ defmodule OliWeb.Components.Delivery.Student do

defp time_remaining(%{end_date: nil} = assigns) do
~H"""
"""
end

Expand Down
2 changes: 1 addition & 1 deletion lib/oli_web/components/header.ex
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ defmodule OliWeb.Components.Header do

def delivery_header(assigns) do
~H"""
<nav class="bg-primary-24 h-[111px] flex items-center pl-4 pr-10">
<nav class="bg-primary-24 dark h-[111px] flex items-center pl-4 pr-10">
<a class="navbar-brand torus-logo my-1 mr-auto" href={~p"/"}>
<%= brand_logo(Map.merge(assigns, %{class: "d-inline-block align-top mr-2"})) %>
</a>
Expand Down
14 changes: 9 additions & 5 deletions lib/oli_web/components/layouts/student_delivery_lesson.html.heex
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<div id="live_flash_container" class="fixed top-14 w-full mx-auto z-50">
<%= if live_flash(@flash, :info) do %>
<%= if Phoenix.Flash.get(@flash, :info) do %>
<div class="alert alert-info flex flex-row" role="alert">
<div class="flex-1">
<%= live_flash(@flash, :info) %>
<%= Phoenix.Flash.get(@flash, :info) %>
</div>

<button
Expand All @@ -18,10 +18,10 @@
</div>
<% end %>

<%= if live_flash(@flash, :error) do %>
<%= if Phoenix.Flash.get(@flash, :error) do %>
<div class="alert alert-danger flex flex-row" role="alert">
<div class="flex-1">
<%= live_flash(@flash, :error) %>
<%= Phoenix.Flash.get(@flash, :error) %>
</div>

<button
Expand Down Expand Up @@ -62,7 +62,11 @@
<%= react_component("Components.OfflineDetector") %>
</div>
<.back_arrow
to={assigns[:request_path]}
to={
if assigns[:request_path] in [""],
do: ~p"/sections/#{@section.slug}/learn?target_resource_id=#{@current_page["id"]}",
else: assigns[:request_path]
}
show_sidebar={assigns[:show_sidebar]}
view={assigns[:view]}
/>
Expand Down
29 changes: 26 additions & 3 deletions lib/oli_web/controllers/cognito_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ defmodule OliWeb.CognitoController do
"community_id" => community_id
} = params
) do
case Accounts.setup_sso_user(conn.assigns.claims, community_id) do
{:ok, user} ->
case Accounts.setup_sso_user(conn.assigns.claims, community_id, link_author: true) do
{:ok, user, author} ->
conn
|> create_pow_user(:user, user)
|> maybe_send_invite_email(author)
|> redirect(to: ~p"/sections")

{:error, %Ecto.Changeset{}} ->
Expand All @@ -43,7 +44,7 @@ defmodule OliWeb.CognitoController do
} = params
) do
with anchor when not is_nil(anchor) <- fetch_product_or_project(params),
{:ok, user} <- Accounts.setup_sso_user(conn.assigns.claims, community_id) do
{:ok, user, _} <- Accounts.setup_sso_user(conn.assigns.claims, community_id) do
conn
|> create_pow_user(:user, user)
|> create_or_prompt(user, anchor)
Expand Down Expand Up @@ -198,4 +199,26 @@ defmodule OliWeb.CognitoController do
redirect_with_error(conn, error_url, snake_case_to_friendly(error))
end
end

defp maybe_send_invite_email(conn, nil), do: conn

defp maybe_send_invite_email(conn, author) do
brand_name = Application.get_env(:oli, :branding)[:name]

if not is_nil(author.invitation_token) and is_nil(author.invitation_accepted_at) do
token = PowInvitation.Plug.sign_invitation_token(conn, author)

Oli.Email.invitation_email(
author.email,
:infiniscope_invitation,
%{
brand_name: brand_name,
url: ~p"/authoring/invitations/#{token}/edit"
}
)
|> Oli.Mailer.deliver_now()
end

conn
end
end
4 changes: 2 additions & 2 deletions lib/oli_web/controllers/pow.ex
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ defmodule OliWeb.PowController do
conn
end

def resend_user_confirmation_link(conn, %{"id" => id}) do
def resend_user_confirmation_link(conn, %{"user_id" => id}) do
user = Repo.get(User, id)

conn
Expand All @@ -78,7 +78,7 @@ defmodule OliWeb.PowController do
|> redirect(to: Routes.live_path(conn, OliWeb.Users.UsersDetailView, user.id))
end

def resend_author_confirmation_link(conn, %{"id" => id}) do
def resend_author_confirmation_link(conn, %{"user_id" => id}) do
author = Repo.get(Author, id)

conn
Expand Down
Loading

0 comments on commit 15e26ab

Please sign in to comment.