Handle login/logout flows, more navigation, and add notification emails

This commit is contained in:
2017-02-06 01:31:37 -05:00
parent 0df4d2cd0f
commit ebbbf6b4cf
11 changed files with 111 additions and 5 deletions

View File

@@ -132,6 +132,14 @@ SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.environ['SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET'
SOCIAL_AUTH_GOOGLE_OAUTH2_WHITELISTED_DOMAINS = ['andrew.cmu.edu']
SOCIAL_AUTH_GOOGLE_OAUTH2_AUTH_EXTRA_ARGUMENTS = {'hd': 'andrew.cmu.edu' }
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/items/'
LOGIN_URL = '/login/google-oauth2/'
# email settings
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = '465'
EMAIL_USE_SSL = True
EMAIL_HOST_USER = 'fincom.bot@gmail.com'
EMAIL_HOST_PASSWORD = os.environ['EMAIL_PASSWORD']
# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/

View File

@@ -19,6 +19,7 @@ from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^logout$', views.user_logout, name='logout'),
url(r'^items/', include('items.urls')),
url('', include('social_django.urls', namespace='social')),
url(r'^admin/', admin.site.urls),

View File

@@ -1,6 +1,15 @@
from django.http import HttpResponse
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth import logout
from django.template import loader
def index(request):
if request.user.is_authenticated():
return HttpResponseRedirect('/items')
template = loader.get_template('fincom/index.html')
return HttpResponse(template.render({}, request))
def user_logout(request):
logout(request)
return HttpResponseRedirect('/')

View File

@@ -1,5 +1,6 @@
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.core.mail import send_mail
from storages.backends.s3boto3 import S3Boto3Storage
from stdimage.models import StdImageField
from datetime import datetime, date
@@ -59,6 +60,49 @@ class Item(models.Model):
def __str__(self):
return self.committee.name + ": " + self.event + " " + self.desc
def mail_com_chair(self):
send_mail(
'New Reimbursement - ' + self.event + ': ' + self.desc,
'Hey ' + self.committee.chair.first_name + ',\n\n' + \
'Please take a moment to review http://fincom.delt.space/items/' + \
str(self.pk) + ' and approve or reject the request from ' + \
self.created_by.first_name + ' ' + self.created_by.last_name + \
'. If you have any questions, contact the treasurer.\n\n' + \
'Have a fiscally responsible day,\n Fincom Bot',
'fincom.bot@gmail.com',
[self.committee.chair.email],
html_message='Hey ' + self.committee.chair.first_name+',<br><br>' +\
'Please take a moment to review ' + \
'<a href="http://fincom.delt.space/items/' + \
str(self.pk) + '">http://fincom.delt.space/items/' + str(self.pk) +\
'</a> and approve or reject the request from ' + \
self.created_by.first_name + ' ' + self.created_by.last_name + \
'. If you have any questions, contact the treasurer.<br><br>' + \
'Have a fiscally responsible day,<br><br><em>Fincom Bot</em>'
)
def mail_fincom(self):
emails = [s.email for s in User.objects.filter(groups__name='Fincom')]
send_mail(
'Preapproved Reimbursement - ' + self.event + ': ' + self.desc,
'Hey Fincom,\n\n' + \
'Please take a moment to review http://fincom.delt.space/items/' + \
str(self.pk) + ' and approve or reject the request from ' + \
self.created_by.first_name + ' ' + self.created_by.last_name + \
'.\n\nHave a fiscally responsible day,\n Fincom Bot',
'fincom.bot@gmail.com',
emails,
html_message='Hey Fincom,<br><br>' + \
'Please take a moment to review ' + \
'<a href="http://fincom.delt.space/items/' + \
str(self.pk) + '">http://fincom.delt.space/items/' + str(self.pk) +\
'</a> and approve or reject the request from ' + \
self.created_by.first_name + ' ' + self.created_by.last_name + \
'.<br><br>' + \
'Have a fiscally responsible day,<br><br> <em>Fincom Bot</em>'
)
@staticmethod
def parseDate(date_str):
try:

View File

@@ -15,7 +15,7 @@ def authError():
def myItems(user):
if (user.groups.filter(name='Fincom').exists()):
return Items.objects.order_by('-date_filed', 'desc')
return Item.objects.order_by('-date_filed', 'desc')
comms = []
for c in Committee.objects.all():
@@ -42,13 +42,15 @@ def list(request):
@login_required
def details(request, item_id):
I = Item.objects.get(pk=item_id)
if (not isAuthorised(request, I)):
return HttpResponseRedirect('/items/' + str(item_id) + '/edit')
if (not isAuthorised(request, I)
and request.user != I.created_by):
return authError()
template = loader.get_template('items/details.html')
context = {
'I': I,
'approve': isAuthorised(request, I),
}
return HttpResponse(template.render(context, request))
@@ -62,6 +64,7 @@ def approve(request, item_id):
if (I.committee.chair == request.user and
I.status == Item.NEW):
I.status = Item.PREAPPROVED
I.mail_fincom()
elif (request.user.groups.filter(name='Fincom').exists()):
I.status = Item.PROCESSED
@@ -147,6 +150,8 @@ def new_form(request):
item.save()
item.mail_com_chair()
return HttpResponseRedirect('/items')
else:

View File

@@ -26,3 +26,17 @@
font-weight: normal;
}
}
.details {
color: $text;
font-size: 12px;
font-weight: normal;
margin: $pad-m 0;
padding: $pad-l;
border-radius: $pad-s;
border: 1px solid $midgray;
span {
color: $midgray;
}
}

View File

@@ -38,9 +38,23 @@ body {
font-size: 16px;
margin: 0;
}
a {
float: right;
color: $gold;
text-decoration: none;
font-size: 16px;
}
}
.pull-right {
float: right;
margin: $pad-l;
}
.container {
margin-bottom: $pad-xl;
& > div {
margin-left: auto;
margin-right: auto;
@@ -50,6 +64,7 @@ body {
border: solid 1px $midgray;
box-shadow: 0px 3px 9px lighten($shadowgray, 20%);
}
}
.btn {

View File

@@ -7,6 +7,7 @@
</head>
<body>
<div class="nav">
<a href="/logout">logout</a>
<h3>Fincom Web App</h3>
</div>
<div class="container">

View File

@@ -6,13 +6,21 @@
{% include "./item.html" %}
<div class="approve">
{% if I.details %}
<div class="details">
<span>Details:</span><br>
{{ I.details }}</div>
{% endif %}
<div class="status">Status: <span>{{ I.statusText }}</span></div>
<div class="actions">
{% if approve %}
<a href="/items/{{ I.pk }}/approve" class="btn">Approve</a>
<a href="/items/{{ I.pk }}/reject" class="btn">Reject</a>
{% endif %}
<a href="/items/{{ I.pk }}/delete" class="btn">Delete</a>
<a href="/items/{{ I.pk }}/edit" class="btn">Edit</a>
<a href="/items" class="btn">Back</a>
</div>
<a href="{{ I.image.url }}"><img src="{{ I.image.thumbnail.url }}"></a>

View File

@@ -5,6 +5,7 @@
{% block main %}
<div>
<a href="/items" class="btn pull-right">Back</a>
<h1>Edit Reimbursements</h1>
<hr>

View File

@@ -9,7 +9,7 @@
<hr>
<div class="rcol">
Make sure all information is accurate, you submit and itemized receipt, and
Make sure all information is accurate, you submit an itemized receipt, and
you select the correct committee.
</div>