Commit b5c4a124 authored by David Haynes's avatar David Haynes
Browse files

Merge branch '2.2-dev' into 119-search-bar

parents 4b408072 cd3fbef5
Pipeline #887 passed with stage
in 58 seconds
......@@ -14,3 +14,4 @@ venv
.coverage
htmlcov/
.idea
__pycache__/
......@@ -10,8 +10,8 @@ variables:
before_script:
- apt-get update -qy
- apt-get install -y libldap2-dev libsasl2-dev mysql-client libmysqlclient-dev python-mysqldb
- pip install -r requirements.txt
- apt-get install -y mysql-client libmysqlclient-dev python-mysqldb
- pip install -r requirements/ci.txt
- cd go/
- cp settings/settings.py.template settings/settings.py
- cp settings/secret.py.template settings/secret.py
......@@ -31,12 +31,23 @@ Go-py2.7:
image: library/python:2.7
type: test
script:
- python manage.py test
- python manage.py test
Go-py3.4:
image: library/python:3.4
type: test
script:
- python manage.py test
Go-py3.5:
image: library/python:3.5
type: test
script:
- python manage.py test
Go-py3.6:
image: library/python:3.6
type: test
script:
- pip install coverage
- coverage run --source=go --omit=*migrations/* manage.py test
- coverage run --source=go --omit=*migrations/*,*admin.py,*manage.py,*wsgi.py,*settings.py,*secret.py,*__init__.py,*.pyc,*templates/*,*static/* manage.py test
- coverage html -i && grep pc_cov htmlcov/index.html | egrep -o "[0-9]+\%" | awk '{ print "covered " $1;}'
......@@ -2,12 +2,10 @@ FROM python:3.6
ENV PYTHONUNBUFFERED 1
RUN apt-get update
RUN apt-get install libsasl2-dev -y
RUN apt-get install libldap2-dev -y
RUN apt-get install netcat -y
RUN mkdir /go
WORKDIR /go
ADD requirements.txt /go/
RUN pip install -r requirements.txt
ADD /requirements/ /go/
RUN pip install -r base.txt
ADD . /go/
# Future Imports
from __future__ import unicode_literals, absolute_import, print_function, division
# Django Imports
from django.test import TestCase
# App Imports
from .expirelinks import *
"""
Test cases for the functions in expirelinks
"""
class ExpireLinksTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
<!-- include the base html template -->
{% extends 'layouts/base.html' %}
<!-- define the page title block -->
{% block title %}
403 Error &bull; Forbidden
{% endblock %}
<!-- define the content block for the page -->
{% block content %}
<!-- Tell Django to load static files -->
{% load staticfiles %}
<!-- div that contains the 404 page content -->
<div class="row">
<div class="col-md-10 col-md-offset-1 text-center">
<h1>403 Error - Forbidden</h1>
<h3>You are not permitted to access this page, or you have exceeded the maximum limit of submitted links.</h3>
<h3>
Click <a href="{% url 'index' %}">here</a> to return to the home page.
</h3>
<img id="squirrels" src="{% static "img/acorn.png" %}">
<a href="/"><img src="{% static "img/acorn.png" %}" style="width:10vw;"></a>
</div>
</div>
{% endblock %}
......@@ -13,29 +13,39 @@ from go.models import RegisteredUser
register = template.Library()
"""
check if a user is registered
Helper template function to check if a user is registered.
givenUser: The User object that we are checking to see if they are registered
or not.
"""
@register.filter
def is_registered(user):
def is_registered(givenUser):
# try getting the RegisteredUser of the current user
try:
registered = RegisteredUser.objects.get(username=user.username)
getRegisteredUser = RegisteredUser.objects.get(user=givenUser)
# if it works then the user is registered
return True
return getRegisteredUser.registered
# This should never happen
except RegisteredUser.DoesNotExist as ex:
print(ex)
# if they don't exist then they are not registered
return False
"""
check if a user is approved
Helper template function to check if a user is approved.
givenUser: The User object that we are checking to see if they are approved
or not.
"""
@register.filter
def is_approved(user):
def is_approved(givenUser):
# try getting the RegisteredUser of the current user
try:
registered = RegisteredUser.objects.get(username=user.username)
getRegisteredUser = RegisteredUser.objects.get(user=givenUser)
# if they exist, return whether or not they are approved (boolean)
return registered.approved
return getRegisteredUser.approved
# This should never happen
except RegisteredUser.DoesNotExist as ex:
print(ex)
# if they don't exist then they are not approved
return False
# Future Imports
from __future__ import unicode_literals, absolute_import, print_function, division
# Django Imports
from django.test import TestCase
from django.contrib.auth.models import User
# App Imports
from .go_extras import is_registered, is_approved
from go.models import RegisteredUser
"""
Test cases for the template helper functions in go_extras.py
"""
class GoExtrasTest(TestCase):
"""
Create a dummy user to be tested against.
"""
def setUp(self):
User.objects.create(username='dhaynes', password='password')
"""
Test the is_registered function to see if it gives correct false answers
"""
def test_is_registeredFalse(self):
getUser = User.objects.get(username='dhaynes')
getRegisteredUser = RegisteredUser.objects.get(user=getUser)
getRegisteredUser.registered = False
getRegisteredUser.save()
self.assertFalse(is_registered(getUser))
"""
Test the is_registered function to see if it gives correct true answers
"""
def test_is_registeredTrue(self):
getUser = User.objects.get(username='dhaynes')
getRegisteredUser = RegisteredUser.objects.get(user=getUser)
getRegisteredUser.registered = True
getRegisteredUser.save()
self.assertTrue(is_registered(getUser))
"""
Test the is_registered function to see if it gives correct false answers
"""
def test_is_approvedFalse(self):
getUser = User.objects.get(username='dhaynes')
getRegisteredUser = RegisteredUser.objects.get(user=getUser)
getRegisteredUser.approved = False
getRegisteredUser.save()
self.assertFalse(is_approved(getUser))
"""
Test the is_registered function to see if it gives correct true answers
"""
def test_is_approvedTrue(self):
getUser = User.objects.get(username='dhaynes')
getRegisteredUser = RegisteredUser.objects.get(user=getUser)
getRegisteredUser.approved = False
getRegisteredUser.save()
self.assertFalse(is_approved(getUser))
# Future Imports
from __future__ import unicode_literals, absolute_import, print_function, division
# Django Imports
from django.test import TestCase
# App Imports
from go.cas_callbacks import pfparse, pfinfo, create_user
"""
Test cases for the functions in call_callbacks.
"""
class CasCallbacksTest(TestCase):
"""
Presently enrolled student who has been added to peoplefinder
"""
def test_pf_peoplefinder_method(self):
actual = pfinfo('dhaynes3')
expected = ['David', 'Haynes']
self.assertEqual(expected, actual)
"""
Test the parsing method to ensure that first and last names are seperated
accordingly and correctly.
"""
def test_pfparse_peoplefinder_method(self):
actual = pfparse("Haynes, David M")
expected = ['David', 'Haynes']
self.assertEqual(expected, actual)
"""
student no longer in peoplefinder, or who hasn't yet been added
"""
def test_pfinfo_ldap_method(self):
actual = pfinfo('lfaraone')
expected = ['Luke W', 'Faraone']
self.assertEqual(expected, actual)
"""
student employees will have their staff info return before their student info
"""
def test_pfinfo_employee_method(self):
actual = pfinfo('nander13')
expected = ['Nicholas', 'Anderson']
self.assertEqual(expected, actual)
"""
a name not found for either (should never happen, but gracefully handle anyway)
"""
def test_pfinfo_dne(self):
actual = pfinfo('bobama')
expected = ['', '']
self.assertEqual(expected, actual)
# Future Imports
from __future__ import unicode_literals, absolute_import, print_function, division
# Django Imports
from django.test import TestCase
# App Imports
from go.forms import *
"""
Test cases for the URL form
"""
class URLFormTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
"""
Test cases for the Signup form
"""
class SignupForm(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
......@@ -8,19 +8,17 @@ from django.contrib.auth.models import User
# App Imports
from go.models import URL, RegisteredUser
"""
Test cases for the URL Model
"""
class URLTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
"""
Test cases for the RegisteredUser Model
- check if RegisteredUsers are actually made
- check approval and registration status flipping
- check blocking
- check printing
- add in description
- check organization field
- check full name field
- check print(RegisteredUser)
"""
class RegisteredUserTest(TestCase):
......@@ -31,3 +29,23 @@ class RegisteredUserTest(TestCase):
getUser = User.objects.get(username='dhaynes')
getRegisteredUser = RegisteredUser.objects.get(user=getUser)
self.assertTrue(getRegisteredUser)
def test_checkPrint(self):
# expected = '<Registered User: %s - Approval Status: %s>' % (self.user, self.approved)
self.assertTrue(True)
"""
Test cases for the URL Model
- check if URL's are actually created
- modify clicks (social, qr, normal)
- check expiration date creation
- check print function
"""
class URLTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
# Future Imports
from __future__ import unicode_literals, absolute_import, print_function, division
# Django Imports
from django.test import TestCase
# App Imports
from go.views import *
"""
Test cases for the index view
"""
class IndexTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
"""
Test cases for the "view" view
"""
class ViewTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
"""
Test cases for the my_links view
"""
class MyLinksTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
"""
Test cases for the delete view
"""
class DeleteTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
"""
Test cases for the signup view
"""
class SignupTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
"""
Test cases for the redirection view
"""
class RedirectionTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
"""
Test cases for the useradmin view
"""
class UserAdminTest(TestCase):
"""
Default test case, does not actually test anything
"""
def test_Django_Test(self):
self.assertEqual("Hello World!", "Hello World!")
......@@ -12,6 +12,7 @@ from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.models import User
from django.contrib.auth.decorators import user_passes_test, login_required
from django.shortcuts import render, get_object_or_404, redirect
from ratelimit.decorators import ratelimit
# App Imports
from go.models import URL, RegisteredUser
......@@ -46,61 +47,7 @@ def index(request):
# If a POST request is received, then the user has submitted a form and it's
# time to parse the form and create a new URL object
if request.method == 'POST':
# Now we initialize the form again but this time we have the POST
# request
url_form = URLForm(request.POST, host = request.META.get('HTTP_HOST'))
# Django will check the form to make sure it's valid
if url_form.is_valid():
# We don't commit the url object yet because we need to add its
# owner, and parse its date field.
url = url_form.save(commit = False)
url.owner = request.user.registereduser
# If the user entered a short url, it's already been validated,
# so accept it. If they did not, however, then generate a
# random one and use that instead.
short = url_form.cleaned_data.get('short').strip()
# Check if a short URL was entered
if len(short) > 0:
url.short = short
else:
# If the user didn't enter a short url, generate a random
# one. However, if a random one can't be generated, return
# a 500 server error.
random_short = URL.generate_valid_short()
if random_short is None:
return HttpResponseServerError(
render(request, 'admin/500.html', {})
)
else:
url.short = random_short
# Grab the expiration field value. It's currently an unsable
# string value, so we need to parse it into a datetime object
# relative to right now.
expires = url_form.cleaned_data.get('expires')
# Determine what the expiration date is
if expires == URLForm.DAY:
url.expires = timezone.now() + timedelta(days = 1)
elif expires == URLForm.WEEK:
url.expires = timezone.now() + timedelta(weeks = 1)
elif expires == URLForm.MONTH:
url.expires = timezone.now() + timedelta(weeks = 3)
elif expires == URLForm.CUSTOM:
url.expires = url_form.cleaned_data.get('expires_custom')
else:
pass # leave the field NULL
# Make sure that our new URL object is clean, then save it and
# let's redirect to view this baby.
url.full_clean()
url.save()
return redirect('view', url.short)
return redirect('view', post(request).short)
# Render index.html passing the form to the template
return render(request, 'core/index.html', {
......@@ -108,6 +55,65 @@ def index(request):
},
)
#rate limits are completely arbitrary
@ratelimit(key='user', rate='3/m', method='POST', block=True)
@ratelimit(key='user', rate='25/d', method='POST', block=True)
def post(request):
# Now we initialize the form again but this time we have the POST
# request
url_form = URLForm(request.POST, host = request.META.get('HTTP_HOST'))
# Django will check the form to make sure it's valid
if url_form.is_valid():
# We don't commit the url object yet because we need to add its
# owner, and parse its date field.
url = url_form.save(commit = False)
url.owner = request.user.registereduser
# If the user entered a short url, it's already been validated,
# so accept it. If they did not, however, then generate a
# random one and use that instead.
short = url_form.cleaned_data.get('short').strip()
# Check if a short URL was entered
if len(short) > 0:
url.short = short
else:
# If the user didn't enter a short url, generate a random
# one. However, if a random one can't be generated, return
# a 500 server error.
random_short = URL.generate_valid_short()
if random_short is None:
return HttpResponseServerError(
render(request, 'admin/500.html', {})
)
else:
url.short = random_short
# Grab the expiration field value. It's currently an unsable
# string value, so we need to parse it into a datetime object
# relative to right now.
expires = url_form.cleaned_data.get('expires')
# Determine what the expiration date is
if expires == URLForm.DAY:
url.expires = timezone.now() + timedelta(days = 1)
elif expires == URLForm.WEEK:
url.expires = timezone.now() + timedelta(weeks = 1)
elif expires == URLForm.MONTH:
url.expires = timezone.now() + timedelta(weeks = 3)
elif expires == URLForm.CUSTOM:
url.expires = url_form.cleaned_data.get('expires_custom')
else:
pass # leave the field NULL
# Make sure that our new URL object is clean, then save it and
# let's redirect to view this baby.
url.full_clean()
url.save()
return url
"""
This view allows the user to view details about a URL. Note that they
do not need to be logged in to view info.
......@@ -151,7 +157,6 @@ def my_links(request):
},
)
"""
This view deletes a URL if you have the permission to. User must be
logged in and registered, and must also be the owner of the URL.
......
......@@ -2,8 +2,6 @@
from . import secret
import os
AUTH_MODE = "CAS"
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# DEBUG mode is used to view more details when errors occur
......@@ -137,52 +135,25 @@ AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
)
CAS_SERVER_URL = os.environ['cas_url']
CAS_LOGOUT_COMPLETELY = True
CAS_PROVIDE_URL_TO_LOGOUT = True
if AUTH_MODE.lower() == 'ldap':
import ldap
AUTHENTICATION_BACKENDS += (
'django_auth_ldap.backend.LDAPBackend',
)
AUTH_LDAP_SERVER_URI = "ldaps://directory.gmu.edu:636" # server url
AUTH_LDAP_BIND_DN = "ou=people,o=gmu.edu" # bind DN