Commit dc480301 authored by Tanner Prestegard's avatar Tanner Prestegard Committed by GraceDB

Reorganize alerts index and manage password views

Small fixes to the main "index" view for alerts. Move the
manage_password page for LV-EM observers to the ligoauth app and
show a link to it from the navbar to those users.
parent 43b683b2
......@@ -10,7 +10,7 @@ import core.views
from events.feeds import EventFeed, feedview
import events.reports
import events.views
from ligoauth.views import pre_login, post_login, shib_logout
from ligoauth.views import pre_login, post_login, shib_logout, manage_password
import search.views
# Django admin auto-discover
......@@ -33,7 +33,7 @@ urlpatterns = [
template_name='discovery.html'), name="discovery"),
url(r'^events/', include('events.urls')),
url(r'^superevents/', include('superevents.urls')),
url(r'^options/', include('alerts.urls')),
url(r'^alerts/', include('alerts.urls')),
url(r'^feeds/(?P<url>.*)/$', EventFeed()),
url(r'^feeds/$', feedview, name="feeds"),
......@@ -51,6 +51,9 @@ urlpatterns = [
url(r'^post-login/$', post_login, name='post-login'),
url(r'^logout/$', shib_logout, name='logout'),
# Password management
url('^manage-password/$', manage_password, name='manage-password'),
# API URLs
url(r'^api/', include('api.urls')),
# Legacy API URLs - must be maintained!
......
......@@ -21,35 +21,13 @@ class TestIndexView(GraceDbTestBase):
"""LV-EM user can get to index view"""
url = reverse('alerts:index')
response = self.request_as_user(url, "GET", self.lvem_user)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.status_code, 403)
def test_public_user_get(self):
"""Public user can get to index view"""
"""Public user can't get to index view"""
url = reverse('alerts:index')
response = self.request_as_user(url, "GET")
# Should be redirected to login page
self.assertEqual(response.status_code, 302)
class TestManagePasswordView(GraceDbTestBase):
"""Test user access to page for generating basic auth password for API"""
def test_internal_user_get(self):
"""Internal user *can't* get to manage password page"""
url = reverse('alerts:manage-password')
response = self.request_as_user(url, "GET", self.internal_user)
self.assertEqual(response.status_code, 403)
def test_lvem_user_get(self):
"""LV-EM user can get to manage password page"""
url = reverse('alerts:manage-password')
response = self.request_as_user(url, "GET", self.lvem_user)
self.assertEqual(response.status_code, 200)
def test_public_user_get(self):
"""Public user can't get to manage password page"""
url = reverse('alerts:manage-password')
response = self.request_as_user(url, "GET")
self.assertEqual(response.status_code, 403)
......
......@@ -31,9 +31,4 @@ urlpatterns = [
views.EditNotificationView.as_view(), name="edit-notification"),
url(r'^notification/(?P<pk>\d+)/delete/$',
views.DeleteNotificationView.as_view(), name="delete-notification"),
# Manage password
url(r'^manage_password/$', views.managePassword,
name="manage-password"),
]
......@@ -2,35 +2,24 @@ import logging
from django.conf import settings
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.core.mail import EmailMessage
from django.http import (
HttpResponse, HttpResponseRedirect, HttpResponseNotFound,
Http404, HttpResponseForbidden, HttpResponseBadRequest
)
from django.template import RequestContext
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.utils.http import urlencode
from django.utils.safestring import mark_safe
from django.views.generic.edit import FormView, DeleteView, UpdateView
from django.views.generic.base import ContextMixin
from django.views.generic.detail import SingleObjectMixin, DetailView
from django.views.generic.edit import DeleteView, UpdateView
from django.views.generic.detail import DetailView
from django_twilio.client import twilio_client
from core.views import MultipleFormView
from events.permission_utils import lvem_user_required, is_external
from events.models import Label
from ligoauth.decorators import internal_user_required
from .forms import (
PhoneContactForm, EmailContactForm, VerifyContactForm,
EventNotificationForm, SupereventNotificationForm,
)
from .models import Notification, Contact
from .models import Contact, Notification
from .phone import get_twilio_from
......@@ -38,51 +27,18 @@ from .phone import get_twilio_from
logger = logging.getLogger(__name__)
@login_required
###############################################################################
# Generic views ###############################################################
###############################################################################
@internal_user_required
def index(request):
context = {
'notifications': request.user.notification_set.all(),
'contacts': request.user.contact_set.all(),
}
return render(request, 'profile/notifications.html', context=context)
@lvem_user_required
def managePassword(request):
# lvem_user_required only checks for LVEM group membership,
# not the absence of LVC membership. We want this page to be
# forbidden to LVC members - they don't need passwords since they
# have certificate-based access to the API.
if not is_external(request.user):
return HttpResponseForbidden("Forbidden")
# Set up context dictionary
d = { 'username': request.user.username }
if request.method == "POST":
password = User.objects.make_random_password(length=20)
d['password'] = password
request.user.set_password(password)
request.user.date_joined = timezone.now()
request.user.save()
if request.user.has_usable_password():
d['has_password'] = True
# Check if password is expired
# NOTE: This is super hacky because we are using date_joined to store
# the date when the password was set.
password_expiry = request.user.date_joined + \
settings.PASSWORD_EXPIRATION_TIME - timezone.now()
if (password_expiry.total_seconds() < 0):
d['expired'] = True
else:
d['expired'] = False
d['expiration_days'] = password_expiry.days
else:
d['has_password'] = False
return render(request, 'alerts/index.html', context=context)
return render(request, 'profile/manage_password.html', context=d)
###############################################################################
# Notification views ##########################################################
......@@ -154,7 +110,6 @@ class EditNotificationView(UpdateView):
@method_decorator(internal_user_required, name='dispatch')
class DeleteNotificationView(DeleteView):
"""Delete a notification"""
model = Notification
success_url = reverse_lazy('alerts:index')
def get(self, request, *args, **kwargs):
......@@ -243,7 +198,6 @@ class EditContactView(UpdateView):
@method_decorator(internal_user_required, name='dispatch')
class DeleteContactView(DeleteView):
"""Delete a contact"""
model = Contact
success_url = reverse_lazy('alerts:index')
def get(self, request, *args, **kwargs):
......@@ -267,7 +221,6 @@ class DeleteContactView(DeleteView):
class TestContactView(DetailView):
"""Test a contact (must be verified already)"""
# Send alerts to all contact methods
model = Contact
success_url = reverse_lazy('alerts:index')
def get_queryset(self):
......@@ -352,7 +305,6 @@ class VerifyContactView(UpdateView):
@method_decorator(internal_user_required, name='dispatch')
class RequestVerificationCodeView(DetailView):
"""Redirect view for requesting a contact verification code"""
model = Contact
def get_queryset(self):
return self.request.user.contact_set.all()
......
from django.urls import reverse
from core.tests.utils import GraceDbTestBase
class TestManagePasswordView(GraceDbTestBase):
"""Test user access to page for generating basic auth password for API"""
def test_internal_user_get(self):
"""Internal user *can't* get to manage password page"""
url = reverse('manage-password')
response = self.request_as_user(url, "GET", self.internal_user)
self.assertEqual(response.status_code, 403)
def test_lvem_user_get(self):
"""LV-EM user can get to manage password page"""
url = reverse('manage-password')
response = self.request_as_user(url, "GET", self.lvem_user)
self.assertEqual(response.status_code, 200)
def test_public_user_get(self):
"""Public user can't get to manage password page"""
url = reverse('manage-password')
response = self.request_as_user(url, "GET")
self.assertEqual(response.status_code, 403)
import logging
from django.conf import settings
from django.contrib.auth import logout
from django.http import HttpResponseRedirect
from django.shortcuts import resolve_url
from django.contrib.auth import (
logout, get_user_model, update_session_auth_hash,
)
from django.http import HttpResponseRedirect, HttpResponseForbidden
from django.shortcuts import resolve_url, render
from django.urls import reverse
from django.utils import timezone
from .decorators import lvem_observers_only
# Set up user model
UserModel = get_user_model()
# Set up logger
logger = logging.getLogger(__name__)
......@@ -85,3 +94,34 @@ def shib_logout(request):
resolve_url(settings.LOGOUT_REDIRECT_URL))
return HttpResponseRedirect(original_url)
@lvem_observers_only(superuser_allowed=True)
def manage_password(request):
# Set up context dictionary
d = {}
if request.method == "POST":
password = UserModel.objects.make_random_password(length=20)
d['password'] = password
request.user.set_password(password)
request.user.date_joined = timezone.now()
request.user.save()
update_session_auth_hash(request, request.user)
if request.user.has_usable_password():
d['has_password'] = True
# Check if password is expired
# NOTE: This is super hacky because we are using date_joined to store
# the date when the password was set.
password_expiry = request.user.date_joined + \
settings.PASSWORD_EXPIRATION_TIME - timezone.now()
if (password_expiry.total_seconds() < 0):
d['expired'] = True
else:
d['expired'] = False
d['expiration_days'] = password_expiry.days
else:
d['has_password'] = False
return render(request, 'ligoauth/manage_password.html', context=d)
......@@ -69,17 +69,6 @@
{% endif %}
<a class="btn btn-success" href="{% url "alerts:create-notification" %}">Create new notification</a>
<br/><br/>
{% endif %}
{# Show password page only to LV-EM users who are not also internal #}
{# But let the admins (superusers) see it with some additions #}
{% if user_is_lvem and not user_is_internal or user.is_superuser %}
{% if user.is_superuser %}
<h2 style="border: 2px solid red; color: red; display: inline-block;"><b>The following section is only visible to non-internal LV-EM members. You can see it (and this message) because you are a superuser.</b></h2>
{% endif %}
<h1>Passwords for Scripted Access</h1>
<a class="btn btn-dark" href="{% url "alerts:manage-password" %}">Manage password</a>
{% endif %}
{% endblock %}
......@@ -8,7 +8,7 @@
<p>Passwords generated here are intended only for scripted access to the GraceDB <a href={% url "legacy_apiweb:default:root" %}>REST API</a> by LV-EM users.</p>
<p> Your username is: <b>{{ username }}</b></p>
<p> Your username is: <b>{{ user.username }}</b></p>
{% if has_password %}
{% if password %}
<p>Your password is: <b>{{ password }}</b></p>
......@@ -26,7 +26,7 @@
<p>Press the button here to get a new password (or change your existing one):</p>
<form action={% url "alerts:manage-password" %} method="post">
<form action={% url "manage-password" %} method="post">
<input type="submit" value="Get me a password!">
</form>
......
......@@ -8,12 +8,14 @@
<li id="nav-feeds"><a href="{% url "feeds" %}">RSS</a></li>
{% endif %}
<li id="nav-latest"><a href="{% url "latest" %}">Latest</a></li>
{% if user.is_authenticated %}
<li id="nav-userprofile"><a href="{% url "alerts:index" %}">Options</a></li>
{% if user_is_internal %}
<li id="nav-userprofile"><a href="{% url "alerts:index" %}">Alerts</a></li>
{% elif user_is_lvem %}
<li id="nav-userprofile"><a href="{% url "manage-password" %}">Manage Password</a></li>
{% endif %}
<li id="nav-docs"><a href="{% url "home" %}documentation/">Documentation</a></li>
{% if user %}
{% if user.is_staff %}
{% if user.is_superuser %}
<li id="nav-admin-docs"><a href="{% url "home" %}admin_docs/">Admin docs</a></li>
{% endif %}
{% endif %}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment