feat: send_apikey_usage_emails_task() (#7486)

* feat: send_apikey_usage_emails_task

* chore: update test to use task instead of cmd

* chore: add PeriodicTask

* chore: remove old command + empty management dir

* chore: remove now-empty bin/weekly

* refactor: only consider keys that might have events

---------

Co-authored-by: Robert Sparks <rjsparks@nostrum.com>
This commit is contained in:
Jennifer Richards 2024-05-30 10:31:25 -03:00 committed by GitHub
parent 020bdeb058
commit 2ccc230ce7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 54 additions and 81 deletions

View file

@ -1,22 +0,0 @@
#!/bin/bash
# Weekly datatracker jobs.
#
# This script is expected to be triggered by cron from
# /etc/cron.d/datatracker
export LANG=en_US.UTF-8
export PYTHONIOENCODING=utf-8
DTDIR=/a/www/ietf-datatracker/web
cd $DTDIR/
# Set up the virtual environment
source $DTDIR/env/bin/activate
logger -p user.info -t cron "Running $DTDIR/bin/weekly"
# Send out weekly summaries of apikey usage
$DTDIR/ietf/manage.py send_apikey_usage_emails

View file

@ -1,52 +0,0 @@
# Copyright The IETF Trust 2017-2020, All Rights Reserved
# -*- coding: utf-8 -*-
import datetime
from textwrap import dedent
from django.conf import settings
from django.core.management.base import BaseCommand
from django.utils import timezone
import debug # pyflakes:ignore
from ietf.person.models import PersonalApiKey, PersonApiKeyEvent
from ietf.utils.mail import send_mail
class Command(BaseCommand):
"""
Send out emails to all persons who have personal API keys about usage.
Usage is show over the given period, where the default period is 7 days.
"""
help = dedent(__doc__).strip()
def add_arguments(self, parser):
parser.add_argument('-d', '--days', dest='days', type=int, default=7,
help='The period over which to show usage.')
def handle(self, *filenames, **options):
"""
"""
self.verbosity = int(options.get('verbosity'))
days = options.get('days')
keys = PersonalApiKey.objects.filter(valid=True)
for key in keys:
earliest = timezone.now() - datetime.timedelta(days=days)
events = PersonApiKeyEvent.objects.filter(key=key, time__gt=earliest)
count = events.count()
events = events[:32]
if count:
key_name = key.hash()[:8]
subject = "API key usage for key '%s' for the last %s days" %(key_name, days)
to = key.person.email_address()
frm = settings.DEFAULT_FROM_EMAIL
send_mail(None, to, frm, subject, 'utils/apikey_usage_report.txt', {'person':key.person,
'days':days, 'key':key, 'key_name':key_name, 'count':count, 'events':events, } )

View file

@ -41,6 +41,7 @@ from ietf.meeting.factories import MeetingFactory
from ietf.nomcom.factories import NomComFactory
from ietf.person.factories import PersonFactory, EmailFactory, UserFactory, PersonalApiKeyFactory
from ietf.person.models import Person, Email, PersonalApiKey
from ietf.person.tasks import send_apikey_usage_emails_task
from ietf.review.factories import ReviewRequestFactory, ReviewAssignmentFactory
from ietf.review.models import ReviewWish, UnavailablePeriod
from ietf.stats.models import MeetingRegistration
@ -853,9 +854,6 @@ class IetfAuthTests(TestCase):
key2.delete()
def test_send_apikey_report(self):
from ietf.ietfauth.management.commands.send_apikey_usage_emails import Command
from ietf.utils.mail import outbox, empty_outbox
person = RoleFactory(name_id='secr', group__acronym='secretariat').person
url = urlreverse('ietf.ietfauth.views.apikey_create')
@ -880,9 +878,8 @@ class IetfAuthTests(TestCase):
date = str(date_today())
empty_outbox()
cmd = Command()
cmd.handle(verbosity=0, days=7)
send_apikey_usage_emails_task(days=7)
self.assertEqual(len(outbox), len(endpoints))
for mail in outbox:
body = get_payload_text(mail)

View file

@ -5,12 +5,51 @@
import datetime
from celery import shared_task
from django.conf import settings
from django.utils import timezone
from ietf.utils import log
from .models import PersonApiKeyEvent
from ietf.utils.mail import send_mail
from .models import PersonalApiKey, PersonApiKeyEvent
@shared_task
def send_apikey_usage_emails_task(days):
"""Send usage emails to Persons who have API keys"""
earliest = timezone.now() - datetime.timedelta(days=days)
keys = PersonalApiKey.objects.filter(
valid=True,
personapikeyevent__time__gt=earliest,
).distinct()
for key in keys:
events = PersonApiKeyEvent.objects.filter(key=key, time__gt=earliest)
count = events.count()
events = events[:32]
if count:
key_name = key.hash()[:8]
subject = "API key usage for key '%s' for the last %s days" % (
key_name,
days,
)
to = key.person.email_address()
frm = settings.DEFAULT_FROM_EMAIL
send_mail(
None,
to,
frm,
subject,
"utils/apikey_usage_report.txt",
{
"person": key.person,
"days": days,
"key": key,
"key_name": key_name,
"count": count,
"events": events,
},
)
@shared_task
def purge_personal_api_key_events_task(keep_days):
keep_since = timezone.now() - datetime.timedelta(days=keep_days)

View file

@ -241,6 +241,17 @@ class Command(BaseCommand):
),
)
PeriodicTask.objects.get_or_create(
name="Send personal API key usage emails",
task="ietf.person.tasks.send_apikey_usage_emails_task",
kwargs=json.dumps(dict(days=7)),
defaults=dict(
enabled=False,
crontab=self.crontabs["weekly"],
description="Send personal API key usage summary emails for the past week",
),
)
PeriodicTask.objects.get_or_create(
name="Purge old personal API key events",
task="ietf.person.tasks.purge_personal_api_key_events_task",