diff options
author | CruiseDevice | 2018-09-28 15:27:22 +0530 |
---|---|---|
committer | CruiseDevice | 2018-09-28 15:27:22 +0530 |
commit | 4be0d0d89bf8ad0f6a012d1578af181fe5f83b0c (patch) | |
tree | a7298a03115600bbf4e75083c41647f31b8de05b | |
parent | 378838210959b6afd5c22b17dcf2a4792a87bebb (diff) | |
download | sbhs_server-4be0d0d89bf8ad0f6a012d1578af181fe5f83b0c.tar.gz sbhs_server-4be0d0d89bf8ad0f6a012d1578af181fe5f83b0c.tar.bz2 sbhs_server-4be0d0d89bf8ad0f6a012d1578af181fe5f83b0c.zip |
Slot booking and password reset functionality added
- Password reset
- dashboard skeleton for moderator
- Slot booking template
- Experiment views
- update settings.py
-rw-r--r-- | sbhs/templates/account/account_index.html | 2 | ||||
-rw-r--r-- | sbhs/templates/account/home.html | 16 | ||||
-rw-r--r-- | sbhs/templates/base.html | 1 | ||||
-rw-r--r-- | sbhs/templates/slot/new.html | 56 | ||||
-rw-r--r-- | sbhs/urls.py | 40 | ||||
-rw-r--r-- | sbhs/views.py | 435 | ||||
-rw-r--r-- | sbhs_server/settings.py | 10 |
7 files changed, 338 insertions, 222 deletions
diff --git a/sbhs/templates/account/account_index.html b/sbhs/templates/account/account_index.html index 4b95df0..2d5789a 100644 --- a/sbhs/templates/account/account_index.html +++ b/sbhs/templates/account/account_index.html @@ -11,7 +11,7 @@ {{login_form.as_p}} <input type="submit" class="btn btn-primary" value="Login"> - <a href="#">Forgot Password?</a> + <a href="{% url "password_reset" %}">Forgot Password?</a> </form> </div> <div class="span5 pull-right"> diff --git a/sbhs/templates/account/home.html b/sbhs/templates/account/home.html index 16d475a..fa95a26 100644 --- a/sbhs/templates/account/home.html +++ b/sbhs/templates/account/home.html @@ -3,26 +3,20 @@ {% block content %} <div class="container"> <div class="row"> - {% if user.profile.is_moderator %} - <a href="" class="btn btn-info">Show all boards</a> - <a href="" class="btn btn-info">Show all bookings</a> - <a href="" class="btn btn-info">Show all images</a> - <a href="" class="btn btn-info">Test boards</a> - <a href="" class="btn btn-info">Update MID</a> - <a href="" class="btn btn-info">Fetch Logs</a> - {% endif %} <div class="span12" style="position: relative;top: 1.3em;"> <ul class="nav nav-pills"> <li id="home-nav"><a href="">Home</a></li> <li id="book-slot-nav"><a href="{% url 'slot_new' %}">Book slot</a></li> - <li id="view-slot-nav"><a href="">View/Delete slot</a></li> <li id="download-log-nav"><a href="">Download log files</a></li> <li id="video-nav"><a href="">Show video</a></li> + {% if user.profile.is_moderator %} + <li id="admin-nav"><a href="{% url 'dashboard_index' %}">Dashboard</a></li> + {% endif %} <br><br> </ul> </div> - <script> - document.getElementById("home-nav").classList.add("active"); + <script type="text/javascript"> + document.getElementById("home-nav").classList.add("active"); </script> <div class="span12"> <h2>Welcome to Single Board Heater System Lab</h2> diff --git a/sbhs/templates/base.html b/sbhs/templates/base.html index 3a88c8f..c6294a6 100644 --- a/sbhs/templates/base.html +++ b/sbhs/templates/base.html @@ -35,7 +35,6 @@ {% endfor %} </div> {% endif %} - {% block content %} {% endblock %} <br><br><br> diff --git a/sbhs/templates/slot/new.html b/sbhs/templates/slot/new.html index 27a0400..ec999c9 100644 --- a/sbhs/templates/slot/new.html +++ b/sbhs/templates/slot/new.html @@ -1,5 +1,6 @@ {% extends "account/home.html" %} {% load staticfiles %} +{% load custom_filter %} {% load widget_tweaks %} {% block title %} Book Slot @@ -26,46 +27,22 @@ </div> <div class="tab-content col-md-9 col-md-offset-2 main"> <div class = "tab-pane active" id="tab_a"> - <h3>Book Slot</h3> + <br> + <h4>Book future slots:</h4> <form class = "form-horizontal" action = "" method="POST" autocomplete="off"> + <center> <div class = "form-group"> {% csrf_token %} - {% for field in form %} - {% if field.errors %} - <div class = "control-group error"> - <label class = "control-label"> - {{field.label}} - </label> - <div class = "controls"> - {{field}} - <span class = "help-inline"> - {% for error in field.errors %} - {{error}} - {% endfor %} - </span> - </div> - </div> - {% else %} - <div class = "control-group"> - <div class = "col-xs-2"> - <label class = "control-label"> - {{field.label}}: - </label> - <div class = "control"> - {{field}} - {% if field.help_text %} - <p class = "help-inline"> - <small>{{field.help_text}}</small> - </p> - {% endif %} - </div> - </div> - - </div> - {% endif %} - {% endfor %} - <input type="submit" value = "Create" class = "btn btn-info" name="" > + <b>Book for a given date:</b><br/> + {{form.as_p}} + <button class="btn btn-primary" type="submit" name='book_date' value='book_date'>Book Date</button><br/> + <center>OR</center> + <b>Book for current date and time</b><br/> + + <button class="btn btn-primary" type="submit" name="book_now" value="book_now">Book Now</button><br/> </div> + </center> + </form> </div> @@ -91,9 +68,12 @@ {% endif %} <td>{{h.start_time}}</td> - <td>{{h.duration}}</td> - {%if h.start_time >= now %} + <td>{{h.end_time}}</td> + {% compare_slot_time h.start_time h.end_time now as slot_status %} + {%if slot_status == "pending" %} <td><p class="label label-warning">Pending</p></td> + {% elif slot_status == "ongoing" %} + <td><p class="label label-success">Ongoing</p></td> {% else %} <td><p class="label label-danger">Finished </p></td> {% endif %} diff --git a/sbhs/urls.py b/sbhs/urls.py index 5e79b21..81b63c8 100644 --- a/sbhs/urls.py +++ b/sbhs/urls.py @@ -1,9 +1,12 @@ from django.conf.urls import url - +from django.contrib.auth.views import ( + password_reset, password_change, password_change_done, password_reset_done, + password_reset_confirm, password_reset_complete + ) from . import views urlpatterns = [ - ####### Account URLS ######## + ################## Account URLS #################### url(r'^$', views.index, name='pages_index'), url(r'^about/?$', views.about, name='pages_about'), # url(r'^contact/?$', views.contact, name='pages_contact'), @@ -25,5 +28,38 @@ urlpatterns = [ url(r'^account/update_email/$',views.update_email, \ name='update_email'), + # change password urls + url(r'^account/password-change/$', password_change, + {'template_name': 'account/registration/password_change_form.html'}, + name='password_change'), + url(r'^account/password-change/done/$', password_change_done, + {'template_name': 'account/registration/password_change_done.html'}, + name='password_change_done'), + + # restore password urls + url(r'^account/password-reset/$', password_reset, + {'template_name': 'account/registration/password_reset_form.html'}, + name='password_reset'), + url(r'^account/password-reset/done/$', password_reset_done, + {'template_name': 'account/registration/password_reset_done.html'}, + name='password_reset_done'), + url(r'^account/password-reset/confirm/(?P<uidb64>[-\w]+)/(?P<token>[-\w]+)/$', + password_reset_confirm, + {'template_name': 'account/registration/password_reset_confirm.html'}, + name='password_reset_confirm'), + url(r'^account/password-reset/complete/$', password_reset_complete, + {'template_name': 'account/registration/password_reset_complete.html'}, + name='password_reset_complete'), + + ################## Slot Urls ####################### url(r'^slot/new/$',views.slot_new,name='slot_new'), + + ################## Dashboard Urls ###################### + url(r'^dashboard/$',views.dashboard_index, name='dashboard_index'), + + ################## Experiment urls ##################### + url(r'^experiment/check_connection/$',views.check_connection, + name='experiment_check_connection'), + + url(r'^experiment/initiate/$',views.initiation,name='experiment_initiate') ] diff --git a/sbhs/views.py b/sbhs/views.py index 41525a6..803d460 100644 --- a/sbhs/views.py +++ b/sbhs/views.py @@ -13,7 +13,7 @@ import subprocess # import serial from textwrap import dedent from time import gmtime, strftime -from datetime import datetime +from datetime import datetime, timedelta, date from django.urls import reverse from django.conf import settings @@ -29,7 +29,7 @@ from django.contrib.auth import login, logout, authenticate from django.shortcuts import render, redirect, get_object_or_404 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.http import HttpResponse, HttpResponseRedirect,\ - Http404, HttpResponseServerError + Http404, HttpResponseServerError, JsonResponse from .models import Board, Experiment, Profile, Slot#, Webcam from .forms import UserLoginForm, UserRegistrationForm, SlotCreationForm @@ -42,11 +42,12 @@ from . import switch_off from . import switch_onn +LIMIT = 2 # ser = serial.Serial('/dev/ttyUSB0') # required for experiment views currentdir = os.path.dirname( - os.path.abspath(inspect.getfile(inspect.currentframe()))) + os.path.abspath(inspect.getfile(inspect.currentframe()))) parentdir = os.path.dirname(currentdir) sys.path.insert(0, parentdir) @@ -55,12 +56,12 @@ sys.path.insert(0, parentdir) def index(request, next_url=None): - if request.user.is_authenticated(): - return render(request,'account/home.html') - return render(request,"pages/pages_index.html") + if request.user.is_authenticated(): + return render(request,'account/home.html') + return render(request,"pages/pages_index.html") def about(req): - return render(req, "pages/about.html") + return render(req, "pages/about.html") def info(request): @@ -71,190 +72,290 @@ def downloads(req): def theory(req): - return render(req, "pages/theory.html") + return render(req, "pages/theory.html") def procedure(req): - return render(req, "pages/procedure.html") + return render(req, "pages/procedure.html") def experiments(req): - return render(req, "pages/experiments.html") + return render(req, "pages/experiments.html") def feedback(req): - return render(req, "pages/feedback.html") + return render(req, "pages/feedback.html") #########Account Views ########### @email_verified def account_index(request): - if request.user.is_authenticated(): - return render(request,'account/home.html') + if request.user.is_authenticated(): + return render(request,'account/home.html') - return render(request,'account/account_index.html',{ - 'login_form':UserLoginForm(request.POST or None), - 'registration_form':UserRegistrationForm(request.POST or None) - }) + return render(request,'account/account_index.html',{ + 'login_form':UserLoginForm(request.POST or None), + 'registration_form':UserRegistrationForm(request.POST or None) + }) def user_login(request): - user = request.user - context = {} - if user.is_authenticated(): - return account_index(request) - - if request.method == 'POST': - form = UserLoginForm(request.POST) - if form.is_valid(): - cd = form.cleaned_data - user = authenticate(username=cd['username'], - password=cd['password']) - if user is not None: - if user.is_active: - login(request,user) - return redirect('account_enter') - else: - messages.success(request,"Account Disabled") - return redirect('account_enter') - else: - messages.success(request, "Username and/or Password is \ - invalid") - return redirect('account_enter') - else: - context={ - "login_form": form - } - else: - form = UserLoginForm() - context = { - "login_form":form - } - return redirect('account_enter') + user = request.user + context = {} + if user.is_authenticated(): + return account_index(request) + + if request.method == 'POST': + form = UserLoginForm(request.POST) + if form.is_valid(): + cd = form.cleaned_data + user = authenticate(username=cd['username'], + password=cd['password']) + if user is not None: + if user.is_active: + login(request,user) + return redirect('account_enter') + else: + messages.success(request,"Account Disabled") + return redirect('account_enter') + else: + messages.success(request, "Username and/or Password is \ + invalid") + return redirect('account_enter') + else: + context={ + "login_form": form + } + else: + form = UserLoginForm() + context = { + "login_form":form + } + return redirect('account_enter') def user_logout(request): - logout(request) - return redirect('account_enter') + logout(request) + return redirect('account_enter') def user_register(request): - user = request.user - if user.is_authenticated(): - return render(request,'account/home.html') - context={} - if request.method == 'POST': - form = UserRegistrationForm(request.POST) - if form.is_valid(): - u_name, pwd, user_email, key= form.save() - new_user = authenticate(username=u_name,password=pwd) - login(request, new_user) - if user_email and key: - success, msg = send_user_mail(user_email, key) - context = { - 'activation_msg':msg - } - return render(request,'account/activation_status.html', - context - ) - return redirect('account_enter') - else: - return redirect('account_enter') - else: - return redirect('account_enter') + user = request.user + if user.is_authenticated(): + return render(request,'account/home.html') + context={} + if request.method == 'POST': + form = UserRegistrationForm(request.POST) + if form.is_valid(): + u_name, pwd, user_email, key= form.save() + new_user = authenticate(username=u_name,password=pwd) + login(request, new_user) + if user_email and key: + success, msg = send_user_mail(user_email, key) + context = { + 'activation_msg':msg + } + return render(request,'account/activation_status.html', + context + ) + return redirect('account_enter') + else: + return redirect('account_enter') + else: + return redirect('account_enter') def activate_user(request, key): - profile = get_object_or_404(Profile, activation_key=key) - context = {} - context['success'] = False - if profile.is_email_verified: - context['activation_msg'] = "Your account is already verified" - return render(request,'account/activation_status.html',context) - if timezone.now() > profile.key_expiry_time: - content['msg'] = dedent( - """ - Your activation time expired. Please try again - """ - ) - else: - context['success'] = True - profile.is_email_verified=True - profile.save() - context['msg'] = "Your account is activated" - return render(request,'account/activation_status.html',context) + profile = get_object_or_404(Profile, activation_key=key) + context = {} + context['success'] = False + if profile.is_email_verified: + context['activation_msg'] = "Your account is already verified" + return render(request,'account/activation_status.html',context) + if timezone.now() > profile.key_expiry_time: + content['msg'] = dedent( + """ + Your activation time expired. Please try again + """ + ) + else: + context['success'] = True + profile.is_email_verified=True + profile.save() + context['msg'] = "Your account is activated" + return render(request,'account/activation_status.html',context) def new_activation(request, email=None): - context = {} - if request.method == 'POST': - email = request.POST.get('email') - try: - user = User.objects.get(email=email) - except MultipleObjectsReturned: - context['email_err_msg'] = 'Multiple entries found for this email \ - Please change your email' - return render(request,'account/activation_status.html',context) - except ObjectDoesNotExist: - context['success'] = False - context['msg'] = "Your account is not verified. Please verify your \ - account" - return render(request, 'account/activation_status.html',context) - - if not user.profile.is_email_verified: - user.profile.activation_key = generate_activation_key(user.username) - user.profile.key_expiry_time = timezone.now() \ - + timezone.timedelta(minutes=20) - user.profile.save() - new_user_data = User.objects.get(email=email) - success, msg = send_user_mail(new_user_data.email, \ - new_user_data.profile.activation_key) - - if success: - context['activation_msg'] = msg - else: - context['msg'] = msg - else: - context['activation_msg'] = "Your account is already verified" - return render(request,'account/activation_status.html',{}) + context = {} + if request.method == 'POST': + email = request.POST.get('email') + try: + user = User.objects.get(email=email) + except MultipleObjectsReturned: + context['email_err_msg'] = 'Multiple entries found for this email \ + Please change your email' + return render(request,'account/activation_status.html',context) + except ObjectDoesNotExist: + context['success'] = False + context['msg'] = "Your account is not verified. Please verify your \ + account" + return render(request, 'account/activation_status.html',context) + + if not user.profile.is_email_verified: + user.profile.activation_key = generate_activation_key(user.username) + user.profile.key_expiry_time = timezone.now() \ + + timezone.timedelta(minutes=20) + user.profile.save() + new_user_data = User.objects.get(email=email) + success, msg = send_user_mail(new_user_data.email, \ + new_user_data.profile.activation_key) + + if success: + context['activation_msg'] = msg + else: + context['msg'] = msg + else: + context['activation_msg'] = "Your account is already verified" + return render(request,'account/activation_status.html',{}) def update_email(request): - context = {} - if request.method == 'POST': - email = request.POST.get('email') - username = request.POST.get('username') - user = get_object_or_404(User, username=username) - user.email = email - user.save() - return new_activation(request, email) - else: - context['email_err_msg'] = "Please Update your email" - return render(request,'account/activation_status.html',context) + context = {} + if request.method == 'POST': + email = request.POST.get('email') + username = request.POST.get('username') + user = get_object_or_404(User, username=username) + user.email = email + user.save() + return new_activation(request, email) + else: + context['email_err_msg'] = "Please Update your email" + return render(request,'account/activation_status.html',context) @login_required @email_verified def slot_new(request): - user = request.user - slot_history = Slot.objects.filter(user=user).order_by("start_time") - context = {} - now = datetime.now(pytz.timezone("UTC")) - if not request.user.is_authenticated(): - return redirect('account_enter') - if request.method == 'POST': - if request.POST.get('delete') == "delete": - slots = request.POST.getlist("slots") - Slot.objects.filter(id__in=slots).delete() - return redirect('slot_new') - else: - form = SlotCreationForm(request.POST) - - if form.is_valid(): - new_slot = form.save(commit=False) - if new_slot.start_time >= now: - new_slot.user = user - new_slot.save() - messages.success(request,'Slot created successfully.') - else: - messages.error(request, - 'Start time selected' - + ' is before today.' - + 'Please choose again.' - ) - return redirect('slot_new') - else: - form = SlotCreationForm() - context['history']=slot_history - context['form']=form - context['now'] = now - return render(request,'slot/new.html',context) + user = request.user + slot_history = Slot.objects.filter(user=user).order_by("start_time") + context = {} + now = timezone.now() + if not request.user.is_authenticated(): + return redirect('account_enter') + + if request.method == 'POST': + if request.POST.get('delete') == "delete": + slots = request.POST.getlist("slots") + Slot.objects.filter(id__in=slots).delete() + if request.POST.get("book_date") == "book_date": + form = SlotCreationForm(request.POST) + if form.is_valid(): + new_slot = form.save(commit=False) + if new_slot.start_time >= now: + new_slot.end_time = new_slot.start_time + timedelta( + minutes=settings.SLOT_DURATION + ) + new_slot.user = user + new_slot.save() + messages.success(request,'Slot created successfully.') + else: + messages.error(request, + 'Start time selected' + + ' is before today.' + + 'Please choose again.' + ) + if request.POST.get("book_now") == "book_now": + slot_now = Slot.objects.create(user=user, start_time=now, + end_time=now+timedelta(minutes=55) + ) + messages.success(request,'Slot created successfully.') + return redirect("slot_new") + + else: + form = SlotCreationForm() + context['history']=slot_history + context['form']=form + context['now'] = now + return render(request,'slot/new.html',context) + + +################## Moderator Views ########################## + +@login_required +def dashboard_index(request): + context = {} + return render(request,'dashboard/dashboard_index.html',context) + +###################Experiment Views ###################### + +def check_connection(request): + message = {"message":"TESTOK"} + return JsonResponse(message, safe=True, status=200) + +@login_required +def initial_login(request): + """ Logs in an user for conducting the experiment on the specified + board. + Input: req:request object. + Output: HttpResponse object. + """ + + username = request.POST.get("username") + rpi_ip = '' + try: + assigned_mid = 2 + except Exception as e: + return JsonResponse({ + "STATUS":400, + "MESSAGE":{ + "IS_IP":"1", + "DATA":"Invalid username" + } + }) + rpi_ip = '10.102.54.71' + if rpi_ip is None: + return JsonResponse({ + "STATUS":400, + "MESSAGE":{ + "IS_IP":"1", + "DATA":"Board is currently offline" + } + }) + return JsonResponse({ + "STATUS":200, + "MESSAGE":{ + "IS_IP":"1", + "DATA":rpi_ip + } + }) + + +@csrf_exempt +def initiation(request): + username = request.POST.get("username") + password = request.POST.get("password") + user = authenticate(username=username, password=password) + if user: + if user.is_active: + now = timezone.now() + slots = Slot.objects.filter(user=user, + start_time__gte=now, + end_time__lt = now + ) + + slot = slots.last() + if slot: + filename = '' + message = { + "STATUS":1, + "MESSAGE": filename + } + else: + message = { + "STATUS":0, + "MESSAGE":"Slot has ended. Please book the next slot \ + to continue the experiment" + } + else: + message = { + "STATUS":0, + "MESSAGE":"Your account is not activated. Please check your \ + mail for activation link" + } + else: + message = { + "STATUS":0, + "MESSAGE":"Invalid username and password" + } + + return JsonResponse(message, safe=True, status=200)
\ No newline at end of file diff --git a/sbhs_server/settings.py b/sbhs_server/settings.py index 81f8482..3b2a68d 100644 --- a/sbhs_server/settings.py +++ b/sbhs_server/settings.py @@ -11,7 +11,7 @@ https://docs.djangoproject.com/en/1.11/ref/settings/ """ import os -import sbhs_server.credentials as credentials +import sbhs_server.secret as credentials # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -61,7 +61,8 @@ ROOT_URLCONF = 'sbhs_server.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR,'templates')], + 'DIRS': [ + os.path.join(BASE_DIR,'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -170,3 +171,8 @@ PRODUCTION_URL = '127.0.0.1:8000' IS_DEVELOPMENT=False DEFAULT_FROM_EMAIL = EMAIL_HOST_USER + +RASP_PI_IP = [] +# enter comma separated raspberry pi IPs here + +RASPI_SBHS_CONNECTION = True if RASP_PI_IP else False |