Skip to content

Commit

Permalink
Merge branch 'master' into health
Browse files Browse the repository at this point in the history
  • Loading branch information
sritanmotati authored Nov 8, 2024
2 parents 84f4d77 + 618b65c commit 858ab7d
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 3 deletions.
36 changes: 36 additions & 0 deletions backend/clubs/management/commands/osa_perms_updates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand

from clubs.models import Club


class Command(BaseCommand):
help = "Give superuser to hard-coded user accounts affiliated with OSA."
web_execute = True

def handle(self, *args, **kwargs):
User = get_user_model()
content_type = ContentType.objects.get_for_model(Club)
approve_perm = Permission.objects.get(
codename="approve_club", content_type=content_type
)
pending_perm = Permission.objects.get(
codename="see_pending_clubs", content_type=content_type
)
if not settings.OSA_KEYS:
raise ValueError("OSA_KEYS not set in settings")
if not (approvers := Group.objects.filter(name="Approvers").first()):
raise ValueError("Approvers group not found")
for key in settings.OSA_KEYS:
if not key or not (user := User.objects.get(username=key)):
continue
user.is_superuser = True
user.is_staff = True
user.user_permissions.add(approve_perm)
user.user_permissions.add(pending_perm)
approvers.user_set.add(user)
user.save()
approvers.save()
2 changes: 2 additions & 0 deletions backend/pennclubs/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,5 @@

# Cybersource settings
CYBERSOURCE_CLIENT_VERSION = "0.15"

OSA_KEYS = None
2 changes: 2 additions & 0 deletions backend/pennclubs/settings/development.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@
"run_environment": "apitest.cybersource.com",
}
CYBERSOURCE_TARGET_ORIGIN = "https://localhost:3001"

OSA_KEYS = ["gwashington"]
2 changes: 2 additions & 0 deletions backend/pennclubs/settings/production.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,5 @@
"run_environment": "api.cybersource.com",
}
CYBERSOURCE_TARGET_ORIGIN = "https://pennclubs.com"

OSA_KEYS = os.getenv("OSA_KEYS", "").split(",")
28 changes: 28 additions & 0 deletions backend/tests/clubs/test_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -777,3 +777,31 @@ def test_graduate_users_output(self):
"Updated the membership status of 1 student club relationships!",
out.getvalue(),
)


class OsaPermsUpdatesTestCase(TestCase):
def setUp(self):
self.user1 = get_user_model().objects.create_user("gwashington")

def test_osa_perms_updates(self):
# Test error when OSA_KEYS is not set
with mock.patch("django.conf.settings.OSA_KEYS", None):
with self.assertRaises(ValueError):
call_command("osa_perms_updates")
self.assertFalse(self.user1.is_superuser)

with mock.patch("django.conf.settings.OSA_KEYS", ["gwashington"]):
# Test error when Approvers group is not found
with self.assertRaises(ValueError):
call_command("osa_perms_updates")
self.assertFalse(self.user1.is_superuser)

# Create Approvers group
Group.objects.create(name="Approvers")
call_command("osa_perms_updates")
self.user1.refresh_from_db()
self.assertTrue(self.user1.groups.filter(name="Approvers").exists())
self.assertTrue(self.user1.is_staff)
self.assertTrue(self.user1.is_superuser)
self.assertTrue(self.user1.has_perm("approve_club"))
self.assertTrue(self.user1.has_perm("see_pending_clubs"))
77 changes: 75 additions & 2 deletions frontend/components/ClubEditPage/ClubEditCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,49 @@ const Card = ({
</div>
)
}
interface EmailModalProps {
closeModal: () => void
email: string
setEmail: (inp: string) => void
confirmSubmission: () => void
}

const EmailModal = ({
closeModal,
email,
setEmail,
confirmSubmission,
}: EmailModalProps): ReactElement => {
return (
<Modal
width={'450px'}
show={true}
closeModal={closeModal}
marginBottom={false}
>
<div className="card-content mb-2">
<Text className="has-text-danger">
This email will be visible to the public.
<br />
We recommend that you don’t use a personal email, and instead use a
club email.
</Text>
<Field
name="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="input mb-5"
style={{ maxWidth: '350px' }}
></Field>
<div>
<button onClick={confirmSubmission} className="button is-primary">
Confirm
</button>
</div>
</div>
</Modal>
)
}

/**
* Remove fields in an object that are not part of a whitelist.
Expand Down Expand Up @@ -229,6 +272,8 @@ export default function ClubEditCard({
),
)

const [emailModal, showEmailModal] = useState<boolean>(false)

const submit = (data, { setSubmitting, setStatus }): Promise<void> => {
const photo = data.image
if (photo !== null) {
Expand Down Expand Up @@ -850,6 +895,7 @@ export default function ClubEditCard({

const creationDefaults = {
subtitle: '',
email: '',
email_public: true,
accepting_members: false,
size: CLUB_SIZES[0].value,
Expand All @@ -871,9 +917,36 @@ export default function ClubEditCard({
: creationDefaults

return (
<Formik initialValues={initialValues} onSubmit={submit} enableReinitialize>
{({ dirty, isSubmitting }) => (
<Formik
initialValues={initialValues}
onSubmit={(values, actions) =>
submit({ ...values, emailOverride: false }, actions)
}
enableReinitialize
validate={(values) => {
const errors: { email?: string } = {}
if (values.email.includes('upenn.edu') && !emailModal) {
showEmailModal(true)
errors.email = 'Please confirm your email'
}
return errors
}}
validateOnChange={false}
validateOnBlur={false}
>
{({ dirty, isSubmitting, setFieldValue, submitForm, values }) => (
<Form>
{emailModal && (
<EmailModal
closeModal={() => showEmailModal(false)}
email={values.email}
setEmail={(newEmail) => setFieldValue('email', newEmail)}
confirmSubmission={() => {
showEmailModal(false)
submitForm()
}}
/>
)}
{!REAPPROVAL_QUEUE_ENABLED && (
<LiveBanner>
<LiveTitle>Queue Closed for Summer Break</LiveTitle>
Expand Down
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,5 +118,6 @@
},
"engines": {
"node": "^20.0.0"
}
},
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
14 changes: 14 additions & 0 deletions k8s/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,20 @@ export class MyChart extends PennLabsChart {
cmd: ['python', 'manage.py', 'rank'],
});

new CronJob(this, 'update-club-counts', {
schedule: cronTime.everyDayAt(0, 12),
image: backendImage,
secret: clubsSecret,
cmd: ['python', 'manage.py', 'update_club_counts'],
})

new CronJob(this, 'osa-perms-updates', {
schedule: cronTime.every(5).minutes(),
image: backendImage,
secret: clubsSecret,
cmd: ['python', 'manage.py', 'osa_perms_updates'],
});

new CronJob(this, 'daily-notifications', {
schedule: cronTime.onSpecificDaysAt(['monday', 'wednesday', 'friday'], 10, 0),
image: backendImage,
Expand Down

0 comments on commit 858ab7d

Please sign in to comment.