Add authentication and login handling for existing views.

This commit is contained in:
Christopher Charbonneau Wells 2017-08-16 12:46:26 -04:00
parent 9841eaa563
commit 70df49c892
13 changed files with 229 additions and 29 deletions

View File

@ -17,6 +17,6 @@ router.register(r'tummy-times', TummyTimeViewSet)
urlpatterns = [
url(r'^api/', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls',
url(r'^api/auth/', include('rest_framework.urls',
namespace='rest_framework'))
]

View File

@ -20,6 +20,7 @@ ALLOWED_HOSTS = []
INSTALLED_APPS = [
'api',
'babyblotter',
'core',
'rest_framework',
@ -75,6 +76,16 @@ DATABASES = {
}
# Authentication
# https://docs.djangoproject.com/en/1.11/topics/auth/default/
LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login/'
LOGOUT_REDIRECT_URL = '/login/'
# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

View File

@ -0,0 +1,9 @@
{% extends "admin/base.html" %}
{% block title %}{{ title }} | Baby Blotter Admin{% endblock %}
{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Baby Blotter Admin</a></h1>
{% endblock %}
{% block nav-global %}{% endblock %}

View File

@ -0,0 +1,29 @@
{% load static widget_tweaks %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{% block title %}{% endblock %} | Baby Blotter</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css"
integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M"
crossorigin="anonymous">
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"
crossorigin="anonymous">
</head>
<body class="bg-dark registration">
<div id="view-{{ request.resolver_match.view_name }}" class="container">
<div class="text-center mb-4">
<h1 class="display-3 mb-3 text-white"><span class="text-info">Baby</span> Blotter</h1>
</div>
<div class="bg-light p-4 rounded">
{% block content %}{% endblock %}
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,39 @@
{% extends "registration/base.html" %}
{% load static widget_tweaks %}
{% block title %}Login{% endblock %}
{% block content %}
<form class="login-form" method="post" action="{% url 'login' %}">
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}">
<label class="sr-only" for="username-input-group">
{{ form.username.label }}
</label>
<div class="input-group mb-3 fade-in">
<div class="input-group-addon">
<i class="fa fa-user" aria-hidden="true"></i>
</div>
{% render_field form.username name='username' class+='form-control' id='username-input-group' placeholder=form.username.label %}
</div>
<label class="sr-only" for="password-input-group">
{{ form.password.label }}
</label>
<div class="input-group mb-3 fade-in">
<div class="input-group-addon">
<i class="fa fa-lock" aria-hidden="true"></i>
</div>
{% render_field form.password name='password' class+='form-control' id='password-input-group' placeholder=form.password.label %}
</div>
<button class="btn btn-primary w-100 fade-in" type="submit" name="login">
Login
</button>
</form>
<div class="bg-faded text-center px-4 py-3 rounded-bottom">
<a href="{% url 'password_reset' %}" name="reset">Forgot your password?</a>
</div>
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends "registration/base.html" %}
{% block title %}Password Reset Successfully!{% endblock %}
{% block content %}
<div class="text-center mb-0">
<p>Your password has been set. You may go ahead and log in now.</p>
<p class="mb-0"><a href="{{ login_url }}">Log in</a></p>
</div>
{% endblock %}

View File

@ -0,0 +1,47 @@
{% extends "registration/base.html" %}
{% load static widget_tweaks %}
{% block title %}Password Reset{% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{% if form.errors %}
<div class="alert alert-danger">
<p class="mb-0"><strong>Oh snap!</strong> The two passwords
did not match. Please try again.</p>
</div>
{% endif %}
<div class="text-center mb-4">
<p class="mb-0">Enter your new password in each field below.</p>
</div>
<label class="sr-only" for="password1-input-group">
{{ form.new_password1.label }}
</label>
<div class="input-group mb-3 fade-in">
<div class="input-group-addon">
<i class="fa fa-lock" aria-hidden="true"></i>
</div>
{% render_field form.new_password1 name='new_password1' class+='form-control' id='password1-input-group' %}
</div>
<label class="sr-only" for="password2-input-group">
{{ form.new_password2.label }}
</label>
<div class="input-group mb-3 fade-in">
<div class="input-group-addon">
<i class="fa fa-lock" aria-hidden="true"></i>
</div>
{% render_field form.new_password2 name='new_password2' class+='form-control' id='password2-input-group' %}
</div>
<button class="btn btn-primary w-100 fade-in" type="submit" name="reset">
Reset Password
</button>
</form>
{% endblock %}

View File

@ -0,0 +1,15 @@
{% extends "registration/base.html" %}
{% block title %}Reset Email Sent{% endblock %}
{% block content %}
<div class="text-center mb-0">
<p>We've emailed you instructions for setting your
password, if an account exists with the email you entered. You
should receive them shortly.</p>
<p class="mb-0">If you don't receive an email, please make sure you've
entered the address you registered with, and check your spam
folder.</p>
</div>
{% endblock %}

View File

@ -0,0 +1,31 @@
{% extends "registration/base.html" %}
{% load static widget_tweaks %}
{% block title %}Forgot Password{% endblock %}
{% block content %}
<div class="text-center mb-4">
<p class="mb-0">Enter your account email address in the form below. If
the address is valid, you will receive instructions for resetting your
password.</p>
</div>
<form method="post">
{% csrf_token %}
<label class="sr-only" for="email-input-group">
{{ form.email.label }}
</label>
<div class="input-group mb-3 fade-in">
<div class="input-group-addon">
<i class="fa fa-envelope" aria-hidden="true"></i>
</div>
{% render_field form.email name='email' class+='form-control' id='email-input-group' placeholder=form.email.label %}
</div>
<button class="btn btn-primary w-100 fade-in" type="submit" name="reset">
Reset Password
</button>
</form>
{% endblock %}

View File

@ -3,9 +3,16 @@ from __future__ import unicode_literals
from django.conf.urls import url, include
from django.contrib import admin
from django.contrib.auth import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/$', views.LoginView.as_view(), name='login'),
url(r'^logout/$', views.LogoutView.as_view(), name='logout'),
url('^password_reset/$', views.PasswordResetView.as_view(),
name='password_reset',),
url(r'', include('api.urls')),
url(r'', include('core.urls')),
]

View File

@ -27,7 +27,7 @@
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
<ul class="navbar-nav mr-auto">
<li class="nav-item{% if request.path == '/' %} active{% endif %}">
<a class="nav-link" href="{% url 'index' %}"><i class="fa fa-home" aria-hidden="true"></i> Home</a>
<a class="nav-link" href="{% url 'index' %}"><i class="fa fa-dashboard" aria-hidden="true"></i> Dashboard</a>
</li>
<li class="nav-item{% if request.path == '/children/' %} active{% endif %}">
<a class="nav-link" href="{% url 'child-list' %}"><i class="fa fa-child" aria-hidden="true"></i> Children</a>
@ -51,7 +51,7 @@
</div>
</nav>
<div class="container-fluid">
<div id="view-{{ request.resolver_match.view_name }}" class="container-fluid">
{% block content %}{% endblock %}
</div>
</body>

View File

@ -6,7 +6,7 @@ from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.Index.as_view(), name='index'),
url(r'^$', views.Dashboard.as_view(), name='index'),
url(r'children/$', views.ChildList.as_view(), name='child-list'),
url(r'children/add/$', views.ChildAdd.as_view(), name='child-add'),

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.base import TemplateView
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic.list import ListView
@ -8,131 +9,131 @@ from django.views.generic.list import ListView
from .models import Child, DiaperChange, Feeding, Note, Sleep, TummyTime
class Index(TemplateView):
class Dashboard(LoginRequiredMixin, TemplateView):
template_name = 'core/index.html'
class ChildList(ListView):
class ChildList(LoginRequiredMixin, ListView):
model = Child
class ChildAdd(CreateView):
class ChildAdd(LoginRequiredMixin, CreateView):
model = Child
fields = ['first_name', 'last_name', 'birth_date']
success_url = '/children'
class ChildUpdate(UpdateView):
class ChildUpdate(LoginRequiredMixin, UpdateView):
model = Child
fields = ['first_name', 'last_name', 'birth_date']
success_url = '/children'
class ChildDelete(DeleteView):
class ChildDelete(LoginRequiredMixin, DeleteView):
model = Child
success_url = '/children'
class DiaperChangeList(ListView):
class DiaperChangeList(LoginRequiredMixin, ListView):
model = DiaperChange
class DiaperChangeAdd(CreateView):
class DiaperChangeAdd(LoginRequiredMixin, CreateView):
model = DiaperChange
fields = ['child', 'time', 'wet', 'solid', 'color']
success_url = '/changes'
class DiaperChangeUpdate(UpdateView):
class DiaperChangeUpdate(LoginRequiredMixin, UpdateView):
model = DiaperChange
fields = ['child', 'time', 'wet', 'solid', 'color']
success_url = '/changes'
class DiaperChangeDelete(DeleteView):
class DiaperChangeDelete(LoginRequiredMixin, DeleteView):
model = DiaperChange
success_url = '/changes'
class FeedingList(ListView):
class FeedingList(LoginRequiredMixin, ListView):
model = Feeding
class FeedingAdd(CreateView):
class FeedingAdd(LoginRequiredMixin, CreateView):
model = Feeding
fields = ['child', 'start', 'end', 'type', 'method']
success_url = '/feedings'
class FeedingUpdate(UpdateView):
class FeedingUpdate(LoginRequiredMixin, UpdateView):
model = Feeding
fields = ['child', 'start', 'end', 'type', 'method']
success_url = '/feedings'
class FeedingDelete(DeleteView):
class FeedingDelete(LoginRequiredMixin, DeleteView):
model = Feeding
success_url = '/feedings'
class NoteList(ListView):
class NoteList(LoginRequiredMixin, ListView):
model = Note
class NoteAdd(CreateView):
class NoteAdd(LoginRequiredMixin, CreateView):
model = Note
fields = ['child', 'note']
success_url = '/notes'
class NoteUpdate(UpdateView):
class NoteUpdate(LoginRequiredMixin, UpdateView):
model = Note
fields = ['child', 'note']
success_url = '/notes'
class NoteDelete(DeleteView):
class NoteDelete(LoginRequiredMixin, DeleteView):
model = Note
success_url = '/notes'
class SleepList(ListView):
class SleepList(LoginRequiredMixin, ListView):
model = Sleep
class SleepAdd(CreateView):
class SleepAdd(LoginRequiredMixin, CreateView):
model = Sleep
fields = ['child', 'start', 'end']
success_url = '/sleep'
class SleepUpdate(UpdateView):
class SleepUpdate(LoginRequiredMixin, UpdateView):
model = Sleep
fields = ['child', 'start', 'end']
success_url = '/sleep'
class SleepDelete(DeleteView):
class SleepDelete(LoginRequiredMixin, DeleteView):
model = Sleep
success_url = '/sleep'
class TummyTimeList(ListView):
class TummyTimeList(LoginRequiredMixin, ListView):
model = TummyTime
class TummyTimeAdd(CreateView):
class TummyTimeAdd(LoginRequiredMixin, CreateView):
model = TummyTime
fields = ['child', 'start', 'end', 'milestone']
success_url = '/tummy-time'
class TummyTimeUpdate(UpdateView):
class TummyTimeUpdate(LoginRequiredMixin, UpdateView):
model = TummyTime
fields = ['child', 'start', 'end', 'milestone']
success_url = '/tummy-time'
class TummyTimeDelete(DeleteView):
class TummyTimeDelete(LoginRequiredMixin, DeleteView):
model = TummyTime
success_url = '/tummy-time'