Merge branch 'dashboard' into testing
diff --git a/exp_portal/email.py b/exp_portal/email.py
index e17ec33..820d94c 100644
--- a/exp_portal/email.py
+++ b/exp_portal/email.py
@@ -2,8 +2,10 @@
from op_tasks.models import UserProfile
from django.core import mail
from django.conf import settings
+from django.contrib.auth.decorators import login_required
+@login_required(login_url='/tasking/login')
def send_email(request):
if request.method == 'POST':
email_to = request.POST.get('email_to', 'xdataonlineerrors@gmail.com')
@@ -20,8 +22,4 @@
statusMessage = "Email sent!"
elif status == 2:
statusMessage = ""
- return render(request, 'email_form.html', {'userprofiles': userprofiles, 'status': status, 'statusMessage': statusMessage})
-
-
-def printme(string):
- print string
\ No newline at end of file
+ return render(request, 'email_form.html', {'userprofiles': userprofiles, 'status': status, 'statusMessage': statusMessage})
\ No newline at end of file
diff --git a/exp_portal/products.py b/exp_portal/products.py
index e299d19..140cc0f 100644
--- a/exp_portal/products.py
+++ b/exp_portal/products.py
@@ -1,15 +1,21 @@
from django.shortcuts import render, redirect
from op_tasks.models import Product, Dataset
+from django.contrib.auth.decorators import login_required
+@login_required(login_url='/tasking/login')
def view_products(request):
products = Product.objects.all()
return render(request, 'products.html', {'products': products})
+
+@login_required(login_url='/tasking/login')
def view_product_details(request, productname):
product = Product.objects.all().filter(name=productname)[0]
datasets = Dataset.objects.all()
return render(request, 'product_details.html', {'product': product, 'datasets': datasets})
+
+@login_required(login_url='/tasking/login')
def edit_product(request, productpk):
product = Product.objects.get(id=productpk)
product.name = request.POST['product_name']
@@ -27,14 +33,20 @@
return redirect('exp_portal:view_products')
+
+@login_required(login_url='/tasking/login')
def manage_products(request):
products = Product.objects.all()
return render(request, 'products.html', {'products': products})
+
+@login_required(login_url='/tasking/login')
def add_product(request):
datasets = Dataset.objects.all()
return render(request, 'add_product.html', {'datasets': datasets})
+
+@login_required(login_url='/tasking/login')
def new_product(request):
product = Product(name=request.POST['product_name'])
product.url = request.POST['product_url']
diff --git a/exp_portal/tasks.py b/exp_portal/tasks.py
index d9898af..7bd10b4 100644
--- a/exp_portal/tasks.py
+++ b/exp_portal/tasks.py
@@ -3,23 +3,32 @@
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
+@login_required(login_url='/tasking/login')
def view_tasks(request):
tasks = OpTask.objects.all()
datasets = Dataset.objects.all()
return render(request, 'tasks.html', {'tasks': tasks, 'datasets':datasets})
+
+@login_required(login_url='/tasking/login')
def view_completed(request):
completed_tasks = TaskListItem.objects.all().filter(task_complete=True).order_by('-date_complete')
return render(request, 'completed.html', {'completed_tasks': completed_tasks})
+
+@login_required(login_url='/tasking/login')
def view_incomplete(request):
incomplete_tasks = TaskListItem.objects.all().filter(task_complete=False)
return render(request, 'incomplete.html', {'incomplete_tasks': incomplete_tasks})
-
+
+
+@login_required(login_url='/tasking/login')
def add_task(request):
datasets = Dataset.objects.all()
return render(request, 'add_task.html', {'datasets': datasets})
+
+@login_required(login_url='/tasking/login')
def new_task(request):
dataset = Dataset.objects.get(name=request.POST['task_dataset'])
task = OpTask()
@@ -32,9 +41,13 @@
task.save()
return redirect('exp_portal:view_tasks')
+
+@login_required(login_url='/tasking/login')
def manage_tasks(request):
return view_tasks(request)
+
+@login_required(login_url='/tasking/login')
def view_task_details(request, taskname):
task = OpTask.objects.all().filter(name=taskname)[0]
datasets = Dataset.objects.all()
@@ -43,6 +56,8 @@
print dataset.name
return render(request, 'task_details.html', {'task': task, 'datasets': datasets})
+
+@login_required(login_url='/tasking/login')
def edit_task(request, taskpk):
task = OpTask.objects.get(id=taskpk)
task.name = request.POST['task_name']
@@ -59,6 +74,8 @@
return redirect('exp_portal:view_tasks')
+
+@login_required(login_url='/tasking/login')
def delete_task(request, taskpk):
task = OpTask.objects.get(id=taskpk)
task.delete()
diff --git a/exp_portal/users.py b/exp_portal/users.py
index 500ddf4..f4138fb 100644
--- a/exp_portal/users.py
+++ b/exp_portal/users.py
@@ -4,14 +4,18 @@
from django.contrib.auth.models import User
from django.http import JsonResponse
+@login_required(login_url='/tasking/login')
def view_users(request):
userprofiles = UserProfile.objects.all().order_by('-user__last_login')
return render(request, 'users.html', {'userprofiles': userprofiles})
+@login_required(login_url='/tasking/login')
def manage_users(request):
userprofiles = UserProfile.objects.all().order_by('-user__last_login')
return render(request, 'users.html', {'userprofiles': userprofiles})
+
+@login_required(login_url='/tasking/login')
def edit_user(request, userprofilepk):
userprofile = UserProfile.objects.get(id=userprofilepk)
experiment = Experiment.objects.get(name=request.POST['experiment_name'])
@@ -20,11 +24,15 @@
return redirect('exp_portal:view_users')
+
+@login_required(login_url='/tasking/login')
def add_user(request):
experiments = Experiment.objects.all()
products = Product.objects.all()
return render(request, 'add_user.html', {'experiments': experiments, 'products':products})
+
+@login_required(login_url='/tasking/login')
def delete_user(request, userprofilepk):
userprofile = UserProfile.objects.get(id=userprofilepk)
user = userprofile.user
@@ -38,6 +46,8 @@
return redirect('exp_portal:view_users')
+
+@login_required(login_url='/tasking/login')
def new_user(request):
user = User(username=request.POST['username'])
user.set_password(request.POST['password_1'])
@@ -97,9 +107,13 @@
return redirect('exp_portal:view_users')
+
+@login_required(login_url='/tasking/login')
def user_added(request):
return render(request, 'user_added.html')
+
+@login_required(login_url='/tasking/login')
def view_user_tasks(request, profile):
userprofile = UserProfile.objects.all().filter(user_hash=profile)[0]
usertasks = userprofile.tasklistitem_set.all()
@@ -115,6 +129,8 @@
return render(request, 'user_tasks.html', {'userprofile': userprofile, 'experiments':experiments})
+
+@login_required(login_url='/tasking/login')
def add_user_task(request, userpk):
userprofile = UserProfile.objects.get(id=userpk)
datasets = Dataset.objects.all()
@@ -123,6 +139,8 @@
return render(request, 'add_user_task.html', {'userprofile':userprofile,
'datasets': datasets, 'products': products, 'tasks': tasks})
+
+@login_required(login_url='/tasking/login')
def update_user_tasks(request, userpk, datasetpk, productpk, taskpk):
dataset = Dataset.objects.get(id=datasetpk)
userprofile = UserProfile.objects.get(id=userpk)
@@ -138,6 +156,8 @@
return redirect('exp_portal:add_user_task', userpk)
+
+@login_required(login_url='/tasking/login')
def view_users_experiment(request, experiment_name):
experiment = Experiment.objects.get(name=experiment_name)
userprofiles = experiment.userprofile_set.all()
diff --git a/exp_portal/views.py b/exp_portal/views.py
index c2e2b78..6e05ec3 100644
--- a/exp_portal/views.py
+++ b/exp_portal/views.py
@@ -13,6 +13,8 @@
def home_page(request):
return render(request, 'experimenthome.html')
+
+@login_required(login_url='/tasking/login')
def view_status(request):
experiments = Experiment.objects.all()
masterList = {}
@@ -49,16 +51,19 @@
return render(request, 'status.html', {'experimentList': masterList})
+@login_required(login_url='/tasking/login')
def manage_exps(request):
experimentlist = Experiment.objects.all()
return render(request, 'experiments.html', {'experimentlist': experimentlist})
+@login_required(login_url='/tasking/login')
def view_exp_details(request, exppk):
experiment = Experiment.objects.get(id=exppk)
return render(request, 'experiment_details.html', {'experiment':experiment})
+@login_required(login_url='/tasking/login')
def add_exp(request):
if request.method == 'POST':
experiment = Experiment()
@@ -79,6 +84,7 @@
return render(request, 'add_experiment.html')
+@login_required(login_url='/tasking/login')
def edit_exp(request, exppk):
experiment = Experiment.objects.get(id=exppk)
experiment.name = request.POST['exp_name']
@@ -97,16 +103,19 @@
return redirect('exp_portal:manage_exps')
+@login_required(login_url='/tasking/login')
def manage_datasets(request):
datasets = Dataset.objects.all()
return render(request, 'datasets.html', {'datasets':datasets})
+@login_required(login_url='/tasking/login')
def view_dataset_details(request, datasetpk):
dataset = Dataset.objects.get(id=datasetpk)
return render(request, 'dataset_details.html', {'dataset':dataset})
+@login_required(login_url='/tasking/login')
def add_dataset(request):
if request.method == 'POST':
# do update
@@ -121,6 +130,7 @@
return render(request, 'add_dataset.html')
+@login_required(login_url='/tasking/login')
def edit_dataset(request, datasetpk):
dataset = Dataset.objects.get(id=datasetpk)
dataset.name = request.POST['dataset_name']
@@ -132,6 +142,7 @@
return redirect('exp_portal:manage_datasets')
+@login_required(login_url='/tasking/login')
def view_experiment_products(request):
experiments = Experiment.objects.all()
masterList = {}
diff --git a/op_tasks/views.py b/op_tasks/views.py
index d20c68a..b7ea8e0 100755
--- a/op_tasks/views.py
+++ b/op_tasks/views.py
@@ -9,12 +9,21 @@
from django.contrib.auth.models import User
from django.utils import timezone
from elasticsearch import Elasticsearch
+from Crypto.Cipher import AES
import exp_portal
import datetime
from op_tasks.models import Product, UserProfile, TaskListItem, Experiment
+import exceptions
+import hashlib
+import logging
+#import zlib
+#import sqlite
+
+from op_tasks.models import Dataset, Product, OpTask, UserProfile, TaskListItem, Experiment
+logger = logging.getLogger('op_tasks')
def set_cookie(response, key, value, days_expire = 7):
if days_expire is None:
@@ -44,6 +53,7 @@
return len(timestamps)
# manages which prodct is delivered to the current user
+@login_required(login_url='/tasking/login')
def product(request, task_pk):
if request.method == 'POST':
user = request.user
@@ -155,8 +165,46 @@
return render(request, 'task_launch.html', {'tasklistitem': tasklistitem})
+# Get unencrypted username
+def decryptUsername(request):
+ user = request.user
+ return aesDecryptor(user.username)
+
+# decrypt the text passed in
+def aesDecryptor(encryptedText):
+ key = readInKey('fileLocation') #'0123456789abcdef0123456789abcdef'
+ IV = 16 * '\x00' # Initialization vector: discussed later
+ mode = AES.MODE_CBC
+ decryptor = AES.new(key, mode, IV=IV)
+ plainText = decryptor.decrypt(ciphertext)
+ return plainText
+
+# encrypt the text passed in
+def aesEncryptor(plainText):
+ key = readInKey('fileLocation') #'0123456789abcdef0123456789abcdef'
+ IV = 16 * '\x00' # Initialization vector: discussed later
+ mode = AES.MODE_CBC
+ encryptor = AES.new(key, mode, IV=IV)
+ if len(plainText) % 16 != 0:
+ plainText += ' ' * (16 - len(plainText) % 16)
+ cipherText = encryptor.encrypt(plainText)
+ return cipherText;
+
+def readInKey(fileLocation):
+ # Open file and read in key (TODO)
+ # For now, create a 32-bit key from a phrase
+ key = createKeyFromPhrase("WouldYouLike12Muffins?")
+ return key
+
+# Will not need this function when key is read in from file while running operationally
+def createKeyFromPhrase(phrase):
+ key = hashlib.sha256(phrase).digest()
+ return key
+
# cretaes a new user and assigns tasks
def register(request):
+ logging.basicConfig(filename='/home/ubuntu/logs/log.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
+ logger.debug("Logging is working.")
# Like before, get the request's context.
context = RequestContext(request)
@@ -171,6 +219,10 @@
# Once hashed, we can update the user object.
user = User(username=request.POST['username'])
user.set_password(request.POST['password'])
+ logger.debug("This is the username: ", user.username, " and password, before encryption: ", user.password)
+ user.username = aesEncryptor(user.username).decode('utf-16')
+ #user.username = sqlite3.Binary(zlib.compress(aesEncryptor(user.username)))
+ logger.debug("This is the username: ", user.username, " and password, after encryption: ", user.password)
user.email = user.username
user.save()
@@ -186,6 +238,7 @@
# Now we save the UserProfile model instance.
userprofile.save()
+ logger.debug("Saved the user profile successfully")
# Finally we assign tasks to the new user
# Get a random product, get a random order of tasks
@@ -242,6 +295,8 @@
# Gather the username and password provided by the user.
# This information is obtained from the login form.
username = request.POST['username']
+ #username = sqlite3.Binary(zlib.compress(aesEncryptor(username)))
+ username = aesEncryptor(username).decode('utf-16')
password = request.POST['password']
# print "Login attempt by " + username + " at " + datetime
@@ -356,4 +411,4 @@
def view_profile(request):
- return render(request, 'user_profile.html', {'user': request.user})
\ No newline at end of file
+ return render(request, 'user_profile.html', {'user': request.user})
diff --git a/uploads/views.py b/uploads/views.py
index a070caa..a75fea1 100644
--- a/uploads/views.py
+++ b/uploads/views.py
@@ -2,6 +2,7 @@
from op_tasks.models import Experiment
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
+from django.contrib.auth.decorators import login_required
import pandas
import numpy as np
@@ -11,6 +12,7 @@
from models import Document
from forms import DocumentForm
+@login_required(login_url='/tasking/login')
def expuploads(request):
# Handle file uploads
if request.method == 'POST':
@@ -28,13 +30,14 @@
return render(request, 'expuploads.html', {'form': form, 'experiments': experiments})
def handle_uploaded_file(f, dirname):
- path = os.path.join('static/results/', dirname)
+ path = os.path.join('../static/results', dirname)
try:
- os.mkdir(path)
- except:
- pass
+ os.makedirs(path)
+ except OSError as e:
+ print e
+ print 'unable to create directory ' + path
file = f['docfile']
- with open(path + '/' + file.name, 'wb+') as destination:
+ with open(path + '/' + file.name, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
@@ -54,7 +57,7 @@
tools = pandas.DataFrame(workingData['SYS.FIL.APP.']).drop_duplicates().sort('SYS.FIL.APP.').reset_index();
del tools['index']
tools.columns = ['Tools']
- tools.to_json(path_or_buf=path + '\/' + "tools.json")
+ tools.to_json(path_or_buf=path + '/' + "tools.json")
metrics = {'load':{'col':'PST.EXP.CLD.CP.','max':5},
@@ -86,4 +89,4 @@
array.append(subarray)
d = pandas.DataFrame(array, columns=('Tool', 'Range'))
result = pandas.ordered_merge(df,d)
- result.to_csv(path_or_buf=path + '\/' + str(key) + '.csv', sep=',',na_rep='0',index=False)
\ No newline at end of file
+ result.to_csv(path_or_buf=path + '/' + str(key) + '.csv', sep=',',na_rep='0',index=False)
\ No newline at end of file
diff --git a/xdata/settings.py b/xdata/settings.py
index b1f45a8..493429f 100755
--- a/xdata/settings.py
+++ b/xdata/settings.py
@@ -46,6 +46,7 @@
'exp_portal',
'developer',
'uploads',
+ 'axes',
)
MIDDLEWARE_CLASSES = (
@@ -55,6 +56,7 @@
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
+ 'axes.middleware.FailedLoginMiddleware',
)
ROOT_URLCONF = 'xdata.urls'
@@ -72,9 +74,17 @@
# https://docs.djangoproject.com/en/1.6/ref/settings/#databases
DATABASES = {
+# 'default': {
+# 'ENGINE': 'django.db.backends.sqlite3',
+# 'NAME': os.path.join(BASE_DIR, '../db', 'db.sqlite3'),
+# }
'default': {
- 'ENGINE': 'django.db.backends.sqlite3',
- 'NAME': os.path.join(BASE_DIR, '../db', 'db.sqlite3'),
+ 'ENGINE': 'django.db.backends.postgresql_psycopg2',
+ 'NAME': 'xdatadb',
+ 'USER': 'xdatauser',
+ 'PASSWORD': 'xd@t@!',
+ 'HOST': '127.0.0.1',
+ 'PORT': '',
}
}
@@ -118,4 +128,9 @@
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'xdataonline@gmail.com'
EMAIL_HOST_PASSWORD = MY_EMAIL_PASSWORD
-EMAIL_PORT = 587
\ No newline at end of file
+EMAIL_PORT = 587
+
+# After three failed logins, require users to wait 5 minutes before they can attempt to log in again
+AXES_LOGIN_FAILURE_LIMIT = 3
+from datetime import timedelta
+AXES_COOLOFF_TIME=timedelta(seconds = 300)
diff --git a/xdata/urls.py b/xdata/urls.py
index b9feb46..6b8c79a 100755
--- a/xdata/urls.py
+++ b/xdata/urls.py
@@ -10,7 +10,7 @@
# include urls for op_tasks and administration pages
url(r'^tasking/', include('op_tasks.urls', namespace="op_tasks")),
url(r'^experiment/', include('exp_portal.urls', namespace="exp_portal")),
- url(r'^developer/', include('developer.urls', namespace="developer")),
+ # url(r'^developer/', include('developer.urls', namespace="developer")),
url(r'^user_feedback/', views.user_feedback_home, name='user_feedback_home'),
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('uploads.urls')),