mirror of https://github.com/snachodog/mybuddy.git
Add authentication and login handling for existing views.
This commit is contained in:
parent
9841eaa563
commit
70df49c892
|
@ -17,6 +17,6 @@ router.register(r'tummy-times', TummyTimeViewSet)
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^api/', include(router.urls)),
|
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'))
|
namespace='rest_framework'))
|
||||||
]
|
]
|
||||||
|
|
|
@ -20,6 +20,7 @@ ALLOWED_HOSTS = []
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'api',
|
'api',
|
||||||
|
'babyblotter',
|
||||||
'core',
|
'core',
|
||||||
|
|
||||||
'rest_framework',
|
'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
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
# https://docs.djangoproject.com/en/1.11/topics/i18n/
|
||||||
|
|
||||||
|
|
|
@ -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 %}
|
|
@ -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>
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -3,9 +3,16 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from django.contrib.auth import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^admin/', admin.site.urls),
|
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('api.urls')),
|
||||||
url(r'', include('core.urls')),
|
url(r'', include('core.urls')),
|
||||||
]
|
]
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
|
<div class="collapse navbar-collapse" id="navbarsExampleDefault">
|
||||||
<ul class="navbar-nav mr-auto">
|
<ul class="navbar-nav mr-auto">
|
||||||
<li class="nav-item{% if request.path == '/' %} active{% endif %}">
|
<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>
|
||||||
<li class="nav-item{% if request.path == '/children/' %} active{% endif %}">
|
<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>
|
<a class="nav-link" href="{% url 'child-list' %}"><i class="fa fa-child" aria-hidden="true"></i> Children</a>
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="container-fluid">
|
<div id="view-{{ request.resolver_match.view_name }}" class="container-fluid">
|
||||||
{% block content %}{% endblock %}
|
{% block content %}{% endblock %}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -6,7 +6,7 @@ from django.conf.urls import url
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
urlpatterns = [
|
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/$', views.ChildList.as_view(), name='child-list'),
|
||||||
url(r'children/add/$', views.ChildAdd.as_view(), name='child-add'),
|
url(r'children/add/$', views.ChildAdd.as_view(), name='child-add'),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.views.generic.base import TemplateView
|
from django.views.generic.base import TemplateView
|
||||||
from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||||
from django.views.generic.list import ListView
|
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
|
from .models import Child, DiaperChange, Feeding, Note, Sleep, TummyTime
|
||||||
|
|
||||||
|
|
||||||
class Index(TemplateView):
|
class Dashboard(LoginRequiredMixin, TemplateView):
|
||||||
template_name = 'core/index.html'
|
template_name = 'core/index.html'
|
||||||
|
|
||||||
|
|
||||||
class ChildList(ListView):
|
class ChildList(LoginRequiredMixin, ListView):
|
||||||
model = Child
|
model = Child
|
||||||
|
|
||||||
|
|
||||||
class ChildAdd(CreateView):
|
class ChildAdd(LoginRequiredMixin, CreateView):
|
||||||
model = Child
|
model = Child
|
||||||
fields = ['first_name', 'last_name', 'birth_date']
|
fields = ['first_name', 'last_name', 'birth_date']
|
||||||
success_url = '/children'
|
success_url = '/children'
|
||||||
|
|
||||||
|
|
||||||
class ChildUpdate(UpdateView):
|
class ChildUpdate(LoginRequiredMixin, UpdateView):
|
||||||
model = Child
|
model = Child
|
||||||
fields = ['first_name', 'last_name', 'birth_date']
|
fields = ['first_name', 'last_name', 'birth_date']
|
||||||
success_url = '/children'
|
success_url = '/children'
|
||||||
|
|
||||||
|
|
||||||
class ChildDelete(DeleteView):
|
class ChildDelete(LoginRequiredMixin, DeleteView):
|
||||||
model = Child
|
model = Child
|
||||||
success_url = '/children'
|
success_url = '/children'
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeList(ListView):
|
class DiaperChangeList(LoginRequiredMixin, ListView):
|
||||||
model = DiaperChange
|
model = DiaperChange
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeAdd(CreateView):
|
class DiaperChangeAdd(LoginRequiredMixin, CreateView):
|
||||||
model = DiaperChange
|
model = DiaperChange
|
||||||
fields = ['child', 'time', 'wet', 'solid', 'color']
|
fields = ['child', 'time', 'wet', 'solid', 'color']
|
||||||
success_url = '/changes'
|
success_url = '/changes'
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeUpdate(UpdateView):
|
class DiaperChangeUpdate(LoginRequiredMixin, UpdateView):
|
||||||
model = DiaperChange
|
model = DiaperChange
|
||||||
fields = ['child', 'time', 'wet', 'solid', 'color']
|
fields = ['child', 'time', 'wet', 'solid', 'color']
|
||||||
success_url = '/changes'
|
success_url = '/changes'
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeDelete(DeleteView):
|
class DiaperChangeDelete(LoginRequiredMixin, DeleteView):
|
||||||
model = DiaperChange
|
model = DiaperChange
|
||||||
success_url = '/changes'
|
success_url = '/changes'
|
||||||
|
|
||||||
|
|
||||||
class FeedingList(ListView):
|
class FeedingList(LoginRequiredMixin, ListView):
|
||||||
model = Feeding
|
model = Feeding
|
||||||
|
|
||||||
|
|
||||||
class FeedingAdd(CreateView):
|
class FeedingAdd(LoginRequiredMixin, CreateView):
|
||||||
model = Feeding
|
model = Feeding
|
||||||
fields = ['child', 'start', 'end', 'type', 'method']
|
fields = ['child', 'start', 'end', 'type', 'method']
|
||||||
success_url = '/feedings'
|
success_url = '/feedings'
|
||||||
|
|
||||||
|
|
||||||
class FeedingUpdate(UpdateView):
|
class FeedingUpdate(LoginRequiredMixin, UpdateView):
|
||||||
model = Feeding
|
model = Feeding
|
||||||
fields = ['child', 'start', 'end', 'type', 'method']
|
fields = ['child', 'start', 'end', 'type', 'method']
|
||||||
success_url = '/feedings'
|
success_url = '/feedings'
|
||||||
|
|
||||||
|
|
||||||
class FeedingDelete(DeleteView):
|
class FeedingDelete(LoginRequiredMixin, DeleteView):
|
||||||
model = Feeding
|
model = Feeding
|
||||||
success_url = '/feedings'
|
success_url = '/feedings'
|
||||||
|
|
||||||
|
|
||||||
class NoteList(ListView):
|
class NoteList(LoginRequiredMixin, ListView):
|
||||||
model = Note
|
model = Note
|
||||||
|
|
||||||
|
|
||||||
class NoteAdd(CreateView):
|
class NoteAdd(LoginRequiredMixin, CreateView):
|
||||||
model = Note
|
model = Note
|
||||||
fields = ['child', 'note']
|
fields = ['child', 'note']
|
||||||
success_url = '/notes'
|
success_url = '/notes'
|
||||||
|
|
||||||
|
|
||||||
class NoteUpdate(UpdateView):
|
class NoteUpdate(LoginRequiredMixin, UpdateView):
|
||||||
model = Note
|
model = Note
|
||||||
fields = ['child', 'note']
|
fields = ['child', 'note']
|
||||||
success_url = '/notes'
|
success_url = '/notes'
|
||||||
|
|
||||||
|
|
||||||
class NoteDelete(DeleteView):
|
class NoteDelete(LoginRequiredMixin, DeleteView):
|
||||||
model = Note
|
model = Note
|
||||||
success_url = '/notes'
|
success_url = '/notes'
|
||||||
|
|
||||||
|
|
||||||
class SleepList(ListView):
|
class SleepList(LoginRequiredMixin, ListView):
|
||||||
model = Sleep
|
model = Sleep
|
||||||
|
|
||||||
|
|
||||||
class SleepAdd(CreateView):
|
class SleepAdd(LoginRequiredMixin, CreateView):
|
||||||
model = Sleep
|
model = Sleep
|
||||||
fields = ['child', 'start', 'end']
|
fields = ['child', 'start', 'end']
|
||||||
success_url = '/sleep'
|
success_url = '/sleep'
|
||||||
|
|
||||||
|
|
||||||
class SleepUpdate(UpdateView):
|
class SleepUpdate(LoginRequiredMixin, UpdateView):
|
||||||
model = Sleep
|
model = Sleep
|
||||||
fields = ['child', 'start', 'end']
|
fields = ['child', 'start', 'end']
|
||||||
success_url = '/sleep'
|
success_url = '/sleep'
|
||||||
|
|
||||||
|
|
||||||
class SleepDelete(DeleteView):
|
class SleepDelete(LoginRequiredMixin, DeleteView):
|
||||||
model = Sleep
|
model = Sleep
|
||||||
success_url = '/sleep'
|
success_url = '/sleep'
|
||||||
|
|
||||||
|
|
||||||
class TummyTimeList(ListView):
|
class TummyTimeList(LoginRequiredMixin, ListView):
|
||||||
model = TummyTime
|
model = TummyTime
|
||||||
|
|
||||||
|
|
||||||
class TummyTimeAdd(CreateView):
|
class TummyTimeAdd(LoginRequiredMixin, CreateView):
|
||||||
model = TummyTime
|
model = TummyTime
|
||||||
fields = ['child', 'start', 'end', 'milestone']
|
fields = ['child', 'start', 'end', 'milestone']
|
||||||
success_url = '/tummy-time'
|
success_url = '/tummy-time'
|
||||||
|
|
||||||
|
|
||||||
class TummyTimeUpdate(UpdateView):
|
class TummyTimeUpdate(LoginRequiredMixin, UpdateView):
|
||||||
model = TummyTime
|
model = TummyTime
|
||||||
fields = ['child', 'start', 'end', 'milestone']
|
fields = ['child', 'start', 'end', 'milestone']
|
||||||
success_url = '/tummy-time'
|
success_url = '/tummy-time'
|
||||||
|
|
||||||
|
|
||||||
class TummyTimeDelete(DeleteView):
|
class TummyTimeDelete(LoginRequiredMixin, DeleteView):
|
||||||
model = TummyTime
|
model = TummyTime
|
||||||
success_url = '/tummy-time'
|
success_url = '/tummy-time'
|
||||||
|
|
Loading…
Reference in New Issue