Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work/google shared drives mikes #549

Merged
Merged
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
7 changes: 7 additions & 0 deletions endorsement/dao/shared_drive.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
r'^(?P<netid>[^@]+)@(uw|(u\.)?washington)\.edu$', re.I)


def shared_drive_lifecycle_expired(drive_record):
"""
Set lifecycle to expired for shared drive
"""
logger.info(f"Shared drive {drive_record} lifecycle expired")


def load_shared_drives_from_csv(file_path):
"""
populate shared drive models
Expand Down
22 changes: 11 additions & 11 deletions endorsement/fixtures/test_data/member.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,54 +2,54 @@
"model": "endorsement.member",
"pk": 1,
"fields": {
"name": "javerage"}},
"netid": "javerage"}},
{
"model": "endorsement.member",
"pk": 2,
"fields": {
"name": "endorsee7"}},
"netid": "endorsee7"}},
{
"model": "endorsement.member",
"pk": 3,
"fields": {
"name": "[email protected]"}},
"netid": "[email protected]"}},
{
"model": "endorsement.member",
"pk": 4,
"fields": {
"name": "endorsee6"}},
"netid": "endorsee6"}},
{
"model": "endorsement.member",
"pk": 5,
"fields": {
"name": "jstaff"}},
"netid": "jstaff"}},
{
"model": "endorsement.member",
"pk": 6,
"fields": {
"name": "jinter"}},
"netid": "jinter"}},
{
"model": "endorsement.member",
"pk": 7,
"fields": {
"name": "endorsee5"}},
"netid": "endorsee5"}},
{
"model": "endorsement.member",
"pk": 8,
"fields": {
"name": "endorsee4"}},
"netid": "endorsee4"}},
{
"model": "endorsement.member",
"pk": 9,
"fields": {
"name": "endorsee3"}},
"netid": "endorsee3"}},
{
"model": "endorsement.member",
"pk": 10,
"fields": {
"name": "endorsee2"}},
"netid": "endorsee2"}},
{
"model": "endorsement.member",
"pk": 11,
"fields": {
"name": "endorsee1"}}]
"netid": "endorsee1"}}]
2 changes: 1 addition & 1 deletion endorsement/management/commands/expire_endorsees.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.core.management.base import BaseCommand
from django.core.mail import mail_managers
from django.template import loader
from endorsement.policy import endorsements_to_expire
from endorsement.policy.endorsement import endorsements_to_expire
from endorsement.dao.endorse import clear_endorsement
import logging
import urllib3
Expand Down
23 changes: 23 additions & 0 deletions endorsement/migrations/0028_auto_20240506_1259.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.2.25 on 2024-05-06 19:59

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('endorsement', '0027_auto_20240503_1436'),
]

operations = [
migrations.RenameField(
model_name='member',
old_name='name',
new_name='netid',
),
migrations.AlterField(
model_name='shareddrive',
name='members',
field=models.ManyToManyField(blank=True, to='endorsement.SharedDriveMember'),
),
]
20 changes: 20 additions & 0 deletions endorsement/migrations/0029_auto_20240508_1240.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 3.2.25 on 2024-05-08 19:40

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('endorsement', '0028_auto_20240506_1259'),
]

operations = [
migrations.RemoveField(
model_name='shareddriverecord',
name='acceptance',
),
migrations.DeleteModel(
name='SharedDriveAcceptance',
),
]
26 changes: 26 additions & 0 deletions endorsement/migrations/0030_shareddriveacceptance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 3.2.25 on 2024-05-08 19:42

from django.db import migrations, models
import django.db.models.deletion
import django_prometheus.models


class Migration(migrations.Migration):

dependencies = [
('endorsement', '0029_auto_20240508_1240'),
]

operations = [
migrations.CreateModel(
name='SharedDriveAcceptance',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('action', models.SmallIntegerField(choices=[(0, 'Accept'), (1, 'Revoke')], default=0)),
('datetime_accepted', models.DateTimeField(auto_now_add=True)),
('member', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='endorsement.member')),
('shared_drive_record', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='endorsement.shareddriverecord')),
],
bases=(django_prometheus.models.ExportModelOperationsMixin('shared_drive_acceptance'), models.Model),
),
]
102 changes: 60 additions & 42 deletions endorsement/models/shared_drive.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@


class MemberManager(models.Manager):
def get_member(self, name):
member, _ = self.get_or_create(name=name)
def get_member(self, netid):
member, _ = self.get_or_create(netid=netid)
return member


class Member(ExportModelOperationsMixin('member'), models.Model):
"""
Member represents user associated with a shared drive
"""
name = models.CharField(max_length=128)
netid = models.CharField(max_length=128)

def json_data(self):
return self.name
return self.netid

objects = MemberManager()

Expand Down Expand Up @@ -52,7 +52,7 @@ class SharedDriveMember(

def json_data(self):
return {
"name": self.member.json_data(),
"netid": self.member.json_data(),
"role": self.role.json_data()
}

Expand Down Expand Up @@ -84,6 +84,9 @@ def json_data(self):
"is_subsidized": self.is_subsidized
}

def __str__(self):
return json.dumps(self.json_data())


class SharedDrive(ExportModelOperationsMixin('shared_drive'), models.Model):
"""
Expand All @@ -94,9 +97,12 @@ class SharedDrive(ExportModelOperationsMixin('shared_drive'), models.Model):
drive_name = models.CharField(max_length=128)
drive_quota = models.ForeignKey(SharedDriveQuota, on_delete=models.PROTECT)
drive_usage = models.IntegerField(null=True)
members = models.ManyToManyField(SharedDriveMember)
members = models.ManyToManyField(SharedDriveMember, blank=True)
query_date = models.DateTimeField(null=True)

def get_members(self):
return [m.member.netid for m in self.members.all()]

def json_data(self):
return {
"drive_id": self.drive_id,
Expand All @@ -108,41 +114,10 @@ def json_data(self):

def __str__(self):
return json.dumps(self.json_data())


class SharedDriveAcceptance(
ExportModelOperationsMixin('shared_drive_acceptance'), models.Model):
"""
SharedDriveAcceptance model records each instance of a shared drive
record being accepted or revoked by a shared drive manager.
"""
ACCEPT = 0
REVOKE = 1

ACCEPTANCE_ACTION_CHOICES = (
(ACCEPT, "Accept"),
(REVOKE, "Revoke"))

member = models.ForeignKey(Member, on_delete=models.PROTECT)
action = models.SmallIntegerField(
default=ACCEPT, choices=ACCEPTANCE_ACTION_CHOICES)
datetime_accepted = models.DateTimeField(auto_now_add=True)

def json_data(self):
return {
"member": self.member.json_data(),
"action": self.ACCEPTANCE_ACTION_CHOICES[self.action][1],
"datetime_accepted": datetime_to_str(self.datetime_accepted)
}

def __str__(self):
return json.dumps(self.json_data())


class SharedDriveRecordManager(models.Manager):
def get_member_drives(self, member_netid, drive_id=None):
parms = {
"shared_drive__members__member__name": member_netid,
"shared_drive__members__member__netid": member_netid,
"is_deleted__isnull": True}

if drive_id:
Expand Down Expand Up @@ -177,7 +152,6 @@ class SharedDriveRecord(
datetime_notice_4_emailed = models.DateTimeField(null=True)
datetime_renewed = models.DateTimeField(null=True)
datetime_expired = models.DateTimeField(null=True)
acceptance = models.ManyToManyField(SharedDriveAcceptance, blank=True)
is_deleted = models.BooleanField(null=True)

objects = SharedDriveRecordManager()
Expand All @@ -204,20 +178,31 @@ def itbill_form_url(self):
f"&remote_key={self.subscription.key_remote}"
f"&shared_drive={self.shared_drive.drive_name}")

@property
def acceptor(self):
if not self.datetime_accepted:
return None

return SharedDriveAcceptance.objects.get(
shared_drive_record=self,
datetime_accepted=self.datetime_accepted)

def get_acceptance(self):
return SharedDriveAcceptance.objects.filter(
shared_drive_record=self)

def set_acceptance(self, member_netid, accept=True):
member = Member.objects.get_member(member_netid)
action = SharedDriveAcceptance.ACCEPT if (
accept) else SharedDriveAcceptance.REVOKE

acceptance = SharedDriveAcceptance.objects.create(
member=member, action=action)
self.acceptance.add(acceptance)
shared_drive_record=self, member=member, action=action)

if accept:
self.datetime_accepted = acceptance.datetime_accepted
else:
self.datetime_expired = acceptance.datetime_accepted
self.is_deleted = True

self.save()

Expand Down Expand Up @@ -245,6 +230,7 @@ def json_data(self):
"datetime_notice_4_emailed": datetime_to_str(
self.datetime_notice_4_emailed),
"datetime_accepted": datetime_to_str(self.datetime_accepted),
"acceptance": [a.json_data() for a in self.get_acceptance()],
"datetime_renewed": datetime_to_str(self.datetime_renewed),
"datetime_expired": datetime_to_str(self.datetime_expired),
"datetime_expiration": datetime_to_str(self.expiration_date),
Expand All @@ -253,3 +239,35 @@ def json_data(self):

def __str__(self):
return json.dumps(self.json_data())


class SharedDriveAcceptance(
ExportModelOperationsMixin('shared_drive_acceptance'), models.Model):
"""
SharedDriveAcceptance model records each instance of a shared drive
record being accepted or revoked by a shared drive manager.
"""
ACCEPT = 0
REVOKE = 1

ACCEPTANCE_ACTION_CHOICES = (
(ACCEPT, "Accept"),
(REVOKE, "Revoke"))

shared_drive_record = models.ForeignKey(
SharedDriveRecord, on_delete=models.PROTECT)
member = models.ForeignKey(
Member, on_delete=models.PROTECT)
action = models.SmallIntegerField(
default=ACCEPT, choices=ACCEPTANCE_ACTION_CHOICES)
datetime_accepted = models.DateTimeField(auto_now_add=True)

def json_data(self):
return {
"member": self.member.json_data(),
"action": self.ACCEPTANCE_ACTION_CHOICES[self.action][1],
"datetime_accepted": datetime_to_str(self.datetime_accepted)
}

def __str__(self):
return json.dumps(self.json_data())
1 change: 1 addition & 0 deletions endorsement/notifications/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from endorsement.models import AccessRecord
from endorsement.dao.notification import send_notification
from endorsement.dao.accessors import get_accessor_email
from endorsement.exceptions import EmailFailureException
from django.template import loader, Template, Context
import logging

Expand Down
3 changes: 2 additions & 1 deletion endorsement/notifications/endorsement.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
from endorsement.dao.user import get_endorsee_email_model
from endorsement.dao import display_datetime
from endorsement.dao.endorse import clear_endorsement
from endorsement.policy import endorsements_to_warn
from endorsement.policy.endorsement import endorsements_to_warn
from endorsement.util.email import uw_email_address
from endorsement.util.string import listed_list
from endorsement.exceptions import EmailFailureException
from django.template import loader, Template, Context
from django.utils import timezone
import re
Expand Down
Loading