Skip to content
Open
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
1 change: 1 addition & 0 deletions admin/nodes/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
re_path(r'^flagged_spam$', views.NodeFlaggedSpamList.as_view(), name='flagged-spam'),
re_path(r'^known_spam$', views.NodeKnownSpamList.as_view(), name='known-spam'),
re_path(r'^known_ham$', views.NodeKnownHamList.as_view(), name='known-ham'),
re_path(r'^embargo_report/$', views.EmbargoReportView.as_view(), name='embargo-report'),
re_path(r'^doi_backlog_list/$', views.DoiBacklogListView.as_view(), name='doi-backlog-list'),
re_path(r'^approval_backlog_list/$', views.ApprovalBacklogListView.as_view(), name='approval-backlog-list'),
re_path(r'^confirm_approve_backlog_list/$', views.ConfirmApproveBacklogView.as_view(), name='confirm-approve-backlog-list'),
Expand Down
51 changes: 51 additions & 0 deletions admin/nodes/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
View,
FormView,
ListView,
TemplateView
)
from django.core.paginator import Paginator, InvalidPage

from admin.base.forms import GuidForm
from admin.base.utils import change_embargo_date
Expand All @@ -39,6 +41,7 @@
SpamStatus,
TrashedFile
)
from osf.models.sanctions import Embargo
from osf.models.admin_log_entry import (
update_admin_log,
NODE_REMOVED,
Expand Down Expand Up @@ -474,6 +477,54 @@ def get_context_data(self, **kwargs):
}


class EmbargoReportView(PermissionRequiredMixin, TemplateView):
"""Report view for inspecting current and overdue embargoed registrations.

Shows:
- pending embargoes that should have been activated
- active embargoes that are past their end date
- upcoming active embargoes
"""
template_name = 'nodes/embargo_report.html'
permission_required = 'osf.view_registration'
raise_exception = True

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
pending_embargoes = Embargo.objects.pending_embargoes().select_related('initiated_by')
active_embargoes = Embargo.objects.active_embargoes().select_related('initiated_by')

pending_overdue_embargoes = [
embargo for embargo in pending_embargoes
if embargo.should_be_embargoed
]

overdue_embargoes = [
embargo for embargo in active_embargoes
if embargo.should_be_completed
]

upcoming_queryset = active_embargoes.filter(
end_date__gte=timezone.now(),
).order_by('end_date')

page_number = self.request.GET.get('page') or 1
paginator = Paginator(upcoming_queryset, 10)
try:
upcoming_page = paginator.page(page_number)
except InvalidPage:
upcoming_page = paginator.page(1)

context.update({
'now': timezone.now(),
'pending_overdue_embargoes': pending_overdue_embargoes,
'overdue_embargoes': overdue_embargoes,
'upcoming_embargoes': upcoming_page.object_list,
'upcoming_page': upcoming_page,
})
return context


class ConfirmApproveBacklogView(RegistrationListView):
template_name = 'nodes/registration_approval_list.html'
permission_required = 'osf.view_registrationapproval'
Expand Down
1 change: 1 addition & 0 deletions admin/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
<li><a href="{% url 'nodes:ia-backlog-list' %}"><i class='fa fa-link'></i> <span>IA Backlog</span></a></li>
<li><a href="{% url 'nodes:doi-backlog-list' %}"><i class='fa fa-link'></i> <span>DOI Backlog</span></a></li>
<li><a href="{% url 'nodes:approval-backlog-list' %}"><i class='fa fa-link'></i> <span>Approval Backlog</span></a></li>
<li><a href="{% url 'nodes:embargo-report' %}"><i class='fa fa-link'></i> <span>Embargo Report</span></a></li>
</ul>
</div>
{% endif %}
Expand Down
157 changes: 157 additions & 0 deletions admin/templates/nodes/embargo_report.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
{% extends "base.html" %}
{% load node_extras %}

{% block content %}
<div class="page-header">
<h1>Embargo Report</h1>
</div>

<h2>Upcoming Active Embargoes</h2>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Registration</th>
<th>Embargo ID</th>
<th>State</th>
<th>Embargo Start</th>
<th>Embargo End</th>
<th>Initiated By</th>
</tr>
</thead>
{% include "util/pagination.html" with items=upcoming_page status='' pagin=False order='' %}
<tbody>
{% for embargo in upcoming_embargoes %}
{% with registration=embargo.registrations.first %}
{% if registration %}
<tr>
<td>
<a href="{{ registration | reverse_node }}">
{{ registration.title | truncatechars:30 }}
</a>
</td>
<td>{{ embargo.id }}</td>
<td>{{ embargo.state }}</td>
<td>{{ embargo.initiation_date|date:"F j, Y P" }}</td>
<td>{{ embargo.end_date|date:"F j, Y P" }}</td>
<td>
{% if embargo.initiated_by %}
<a href="{{ embargo.initiated_by | reverse_user }}">
{{ embargo.initiated_by.fullname }}
</a>
{% else %}
&mdash;
{% endif %}
</td>
</tr>
{% endif %}
{% endwith %}
{% empty %}
<tr>
<td colspan="6">No active embargoes found.</td>
</tr>
{% endfor %}
</tbody>
</table>

<h2>Pending Embargoes Past Pending Window</h2>
<p>These embargoes are still awaiting approval but have passed the automatic activation window.</p>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Registration</th>
<th>Embargo ID</th>
<th>State</th>
<th>Embargo Initiation</th>
<th>Embargo End</th>
<th>Initiated By</th>
</tr>
</thead>
<tbody>
{% for embargo in pending_overdue_embargoes %}
{% with registration=embargo.registrations.first %}
{% if registration %}
<tr>
<td>
<a href="{{ registration | reverse_node }}">
{{ registration.title | truncatechars:30 }}
</a>
</td>
<td>{{ embargo.id }}</td>
<td>{{ embargo.state }}</td>
<td>{{ embargo.initiation_date|date:"F j, Y P" }}</td>
<td>{{ embargo.end_date|date:"F j, Y P" }}</td>
<td>
{% if embargo.initiated_by %}
<a href="{{ embargo.initiated_by | reverse_user }}">
{{ embargo.initiated_by.fullname }}
</a>
{% else %}
&mdash;
{% endif %}
</td>
</tr>
{% endif %}
{% endwith %}
{% empty %}
<tr>
<td colspan="6">No pending embargoes past the pending window.</td>
</tr>
{% endfor %}
</tbody>
</table>

<h2>Active Embargoes Past Pending Window</h2>
<p>These embargoes have an end date in the past but the embargo is still marked as active.</p>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Registration</th>
<th>Embargo ID</th>
<th>State</th>
<th>Embargo End</th>
<th>Is Registration Public?</th>
<th>Initiated By</th>
</tr>
</thead>
<tbody>
{% for embargo in overdue_embargoes %}
{% with registration=embargo.registrations.first %}
{% if registration %}
<tr>
<td>
<a href="{{ registration | reverse_node }}">
{{ registration.title | truncatechars:30 }}
</a>
</td>
<td>{{ embargo.id }}</td>
<td>{{ embargo.state }}</td>
<td>{{ embargo.end_date|date:"F j, Y P" }}</td>
<td>
{% if registration.is_public %}
Yes
{% else %}
No
{% endif %}
</td>
<td>
{% if embargo.initiated_by %}
<a href="{{ embargo.initiated_by | reverse_user }}">
{{ embargo.initiated_by.fullname }}
</a>
{% else %}
&mdash;
{% endif %}
</td>
</tr>
{% endif %}
{% endwith %}
{% empty %}
<tr>
<td colspan="6">No overdue active embargoes found.</td>
</tr>
{% endfor %}
</tbody>
</table>

{% endblock %}

24 changes: 24 additions & 0 deletions osf/models/sanctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,17 @@
return {}


class EmbargoManager(models.Manager):

def pending_embargoes(self):
"""Embargoes that are still awaiting admin approval."""
return self.filter(state=self.model.UNAPPROVED)

def active_embargoes(self):
"""Embargoes that have been approved and are currently in effect."""
return self.filter(state=self.model.APPROVED)


class Embargo(SanctionCallbackMixin, EmailApprovableSanction):
"""Embargo object for registrations waiting to go public."""
SANCTION_TYPE = SanctionTypes.EMBARGO
Expand All @@ -472,6 +483,8 @@
initiated_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.CASCADE)
for_existing_registration = models.BooleanField(default=False)

objects = EmbargoManager()

@property
def is_completed(self):
return self.state == self.COMPLETED
Expand All @@ -497,6 +510,17 @@
def pending_registration(self):
return not self.for_existing_registration and self.is_pending_approval

@property
def should_be_embargoed(self):
return (
(timezone.now() - self.initiation_date) >= osf_settings.EMBARGO_PENDING_TIME
and not self.is_deleted
)

@property
def should_be_completed(self):
return self.end_date and self.end_date < timezone.now() and not self.is_deleted

def _get_registration(self):
return self.registrations.first()

Expand Down Expand Up @@ -925,7 +949,7 @@

registration = self._get_registration()
if registration.is_spammy:
raise NodeStateError('Cannot approve a spammy registration')

Check failure on line 952 in osf/models/sanctions.py

View workflow job for this annotation

GitHub Actions / addons_and_admin

Cannot approve a spammy registration

Check failure on line 952 in osf/models/sanctions.py

View workflow job for this annotation

GitHub Actions / addons_and_admin

Cannot approve a spammy registration

super()._on_complete(event_data)
self.save()
Expand Down
13 changes: 4 additions & 9 deletions scripts/embargo_registrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@


def main(dry_run=True):
pending_embargoes = Embargo.objects.filter(state=Embargo.UNAPPROVED)
pending_embargoes = Embargo.objects.pending_embargoes()
for embargo in pending_embargoes:
if should_be_embargoed(embargo):
if embargo.should_be_embargoed:
if dry_run:
logger.warning('Dry run mode')
try:
Expand Down Expand Up @@ -77,9 +77,9 @@ def main(dry_run=True):

transaction.savepoint_rollback(sid)

active_embargoes = Embargo.objects.filter(state=Embargo.APPROVED)
active_embargoes = Embargo.objects.active_embargoes()
for embargo in active_embargoes:
if embargo.end_date < timezone.now() and not embargo.is_deleted:
if embargo.should_be_completed:
if dry_run:
logger.warning('Dry run mode')
parent_registration = Registration.objects.get(embargo=embargo)
Expand Down Expand Up @@ -117,11 +117,6 @@ def main(dry_run=True):
transaction.savepoint_rollback(sid)


def should_be_embargoed(embargo):
"""Returns true if embargo was initiated more than 48 hours prior."""
return (timezone.now() - embargo.initiation_date) >= settings.EMBARGO_PENDING_TIME and not embargo.is_deleted


@celery_app.task(name='scripts.embargo_registrations')
def run_main(dry_run=True):
if not dry_run:
Expand Down
Loading