Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
SRCT
go
Commits
aaaaa9ef
Commit
aaaaa9ef
authored
Feb 10, 2018
by
David Haynes
🙆
Browse files
Merge branch '167-django-two-dot-oh' into '2.3-dev'
Resolve "Adopt Django 2.0" See merge request
!113
parents
76d358c7
32803248
Pipeline
#2113
passed with stages
in 2 minutes and 29 seconds
Changes
22
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
aaaaa9ef
...
...
@@ -36,12 +36,6 @@ before_script:
-
python manage.py migrate
-
echo "from django.contrib.auth import get_user_model; User = get_user_model(); User.objects.create_superuser('root', 'root@srct.gmu.edu', 'root') " | python manage.py shell
Go-py2.7
:
image
:
library/python:2.7
stage
:
test
script
:
-
python manage.py test
Go-py3.4
:
image
:
library/python:3.4
stage
:
test
...
...
@@ -66,4 +60,4 @@ Go-flake8:
image
:
library/python:3.5
stage
:
lint
script
:
-
flake8 go/ --statistics --exit-zero
\ No newline at end of file
-
flake8 go/ --statistics --exit-zero
go/go/admin.py
View file @
aaaaa9ef
"""
go/admin.py
"""
# Future Imports
from
__future__
import
(
absolute_import
,
division
,
print_function
,
unicode_literals
)
Configure the Django admin pages and apply optional formatting.
"""
# Django Imports
from
django.contrib
import
admin
from
django.contrib.auth.admin
import
UserAdmin
...
...
@@ -18,7 +15,6 @@ class URLAdmin(admin.ModelAdmin):
"""
Define what attributes display in the URL Admin
"""
list_display
=
(
"target"
,
"short"
,
"owner"
,
"clicks"
,
"date_created"
,
"expires"
)
# Register URLAdmin
...
...
@@ -28,7 +24,6 @@ class RegisteredUserInline(admin.StackedInline):
"""
Define an inline admin descriptor for User model
"""
model
=
RegisteredUser
can_delete
=
False
...
...
@@ -36,10 +31,7 @@ class UserAdmin(UserAdmin):
"""
Define a new User admin
"""
# see above class that we defined
inlines
=
(
RegisteredUserInline
,
)
# and modify User to use our new UserAdmin
admin
.
site
.
unregister
(
User
)
admin
.
site
.
register
(
User
,
UserAdmin
)
go/go/cas_callbacks.py
View file @
aaaaa9ef
"""
go/cas_callbacks.py
"""
# Future Imports
from
__future__
import
(
absolute_import
,
division
,
print_function
,
unicode_literals
)
Parse the CAS/PF responses and create users in the database.
"""
# Django Imports
from
django.conf
import
settings
from
django.contrib.auth.models
import
User
...
...
@@ -17,7 +14,6 @@ def pfparse(pf_name_result):
"""
Parse what peoplefinder sends back to us and make a list out of it
"""
# name comes in format of Anderson, Nicholas J
name_list
=
pf_name_result
.
split
(
','
)
# there's random whitespace with the first name
...
...
@@ -37,7 +33,6 @@ def pfinfo(uname):
"""
Get information from peoplefinder
"""
base_url
=
settings
.
PF_URL
url
=
base_url
+
"basic/all/"
+
str
(
uname
)
try
:
...
...
@@ -80,9 +75,8 @@ def pfinfo(uname):
def
create_user
(
tree
):
"""
Create a django user based off of the peoplefinder info we parsed earlier
Create a django user based off of the peoplefinder info we parsed earlier
.
"""
print
(
"Parsing CAS information."
)
try
:
username
=
tree
[
0
][
0
].
text
...
...
@@ -112,10 +106,8 @@ def create_user(tree):
print
(
"Added user's name, %s %s."
%
(
info_name
[
0
],
info_name
[
1
]))
print
(
"User object creation process completed."
)
else
:
print
(
"User object already exists."
)
print
(
"CAS callback successful."
)
except
Exception
as
ex
:
print
(
"Unhandled user creation error:"
,
ex
)
go/go/forms.py
View file @
aaaaa9ef
"""
go/forms.py
"""
# Future Imports
from
__future__
import
(
absolute_import
,
division
,
print_function
,
unicode_literals
)
Configure the layout and styling of the Go's forms.
"""
# Python stdlib Imports
from
datetime
import
datetime
,
timedelta
...
...
@@ -30,29 +28,10 @@ from crispy_forms.layout import HTML, Div, Field, Fieldset, Layout
class
URLForm
(
ModelForm
):
"""
The form that is used in URL creation.
"""
# target -------------------------------------------------------------------
def
clean_target
(
self
):
"""
Prevent redirect loop links
"""
# get the entered target link
target
=
self
.
cleaned_data
.
get
(
'target'
)
# Commented out as this check cannont properly be tested since we cannot
# dynamically generate request.META.get('HTTP_HOST')
# # if the host (go.gmu.edu) is in the entered target link or where it
# # redirects
# if self.host in final_url or self.host in target:
# raise ValidationError("You can't make a Go link to Go silly!")
# else:
# return target
return
target
# Custom target URL field
Define custom fields and then render them onto the template.
"""
# target ------------------------------------------------------------------
target
=
URLField
(
required
=
True
,
label
=
'Long URL (Required)'
,
...
...
@@ -62,23 +41,21 @@ class URLForm(ModelForm):
})
)
# short --------------------------------------------------------------------
# short -------------------------------------------------------------------
def
unique_short
(
value
):
"""
Check to make sure the short url has not been used
"""
try
:
# if we're able to get a URL with the same short url
URL
.
objects
.
get
(
short__iexact
=
value
)
except
URL
.
DoesNotExist
as
ex
:
print
(
ex
)
return
# then raise a ValidationError
raise
ValidationError
(
'Short url already exists.'
)
# Custom short-url field with validators.
short
=
SlugField
(
required
=
False
,
label
=
'Short URL (Optional)'
,
...
...
@@ -88,9 +65,7 @@ class URLForm(ModelForm):
min_length
=
3
,
)
# expires ------------------------------------------------------------------
# Define some string date standards
# expires -----------------------------------------------------------------
DAY
=
'1 Day'
WEEK
=
'1 Week'
MONTH
=
'1 Month'
...
...
@@ -106,7 +81,6 @@ class URLForm(ModelForm):
(
CUSTOM
,
CUSTOM
),
)
# Add preset expiration choices.
expires
=
ChoiceField
(
required
=
True
,
label
=
'Expiration (Required)'
,
...
...
@@ -119,7 +93,6 @@ class URLForm(ModelForm):
"""
Check if the selected date is a valid date
"""
# a valid date is one that is greater than today
if
value
>
timezone
.
now
():
return
...
...
@@ -127,30 +100,18 @@ class URLForm(ModelForm):
else
:
raise
ValidationError
(
'Date must be after today.'
)
# Add a custom expiration choice.
expires_custom
=
DateTimeField
(
required
=
False
,
label
=
'Custom Date'
,
input_formats
=
[
'%m-%d-%Y'
],
validators
=
[
valid_date
],
initial
=
lambda
:
datetime
.
now
()
+
timedelta
(
days
=
1
),
widget
=
DateTimePicker
(
options
=
{
"format"
:
"MM-DD-YYYY"
,
"pickTime"
:
False
,
},
icon_attrs
=
{
"class"
:
"fa fa-calendar"
,
},
)
initial
=
lambda
:
datetime
.
now
()
+
timedelta
(
days
=
1
)
)
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""
On initialization of the form, crispy forms renders this layout
On initialization of the form, crispy forms renders this layout
.
"""
# Grab that host info
self
.
host
=
kwargs
.
pop
(
'host'
,
None
)
super
(
URLForm
,
self
).
__init__
(
*
args
,
**
kwargs
)
...
...
@@ -158,7 +119,7 @@ class URLForm(ModelForm):
self
.
helper
=
FormHelper
()
self
.
helper
.
form_method
=
'POST'
# Some xtra vars for form css purposes
# Some
e
xtra vars for form css purposes
self
.
helper
.
form_class
=
'form-horizontal'
self
.
helper
.
label_class
=
'col-md-1'
self
.
helper
.
field_class
=
'col-md-6'
...
...
@@ -198,7 +159,7 @@ class URLForm(ModelForm):
<h4>Set when you would like your Go address to expire:</h4>
<br />"""
),
'expires'
,
Field
(
'expires_custom'
,
template
=
"crispy/customDateField.html"
),
Field
(
'expires_custom'
),
style
=
"background: rgb(#F6F6F6);"
),
active
=
True
,
template
=
'crispy/accordian-group.html'
),
...
...
@@ -214,19 +175,22 @@ class URLForm(ModelForm):
"""
Metadata about this ModelForm
"""
# what model this form is for
model
=
URL
# what attributes are included
fields
=
[
'target'
]
class
EditForm
(
URLForm
):
"""
The form that is used in editing URLs.
A modification of the URL creation form... now for editing URLs. Inherit
custom form fields for DRY purposes.
"""
def
__init__
(
self
,
*
args
,
**
kwargs
):
"""
On initialization of the form, crispy forms renders this layout
On initialization of the form, crispy forms renders this layout
.
"""
# Grab that host info
self
.
host
=
kwargs
.
pop
(
'host'
,
None
)
super
(
URLForm
,
self
).
__init__
(
*
args
,
**
kwargs
)
...
...
@@ -285,8 +249,11 @@ class EditForm(URLForm):
HTML
(
"""
<br />"""
),
StrictButton
(
'Submit Changes'
,
css_class
=
"btn btn-primary btn-md col-md-4"
,
type
=
'submit'
)))
class
Meta
(
URLForm
.
Meta
):
"""
Metadata about this ModelForm
"""
# what attributes are included
fields
=
URLForm
.
Meta
.
fields
...
...
@@ -294,8 +261,6 @@ class SignupForm(ModelForm):
"""
The form that is used when a user is signing up to be a RegisteredUser
"""
# The full name of the RegisteredUser
full_name
=
CharField
(
required
=
True
,
label
=
'Full Name (Required)'
,
...
...
@@ -304,7 +269,6 @@ class SignupForm(ModelForm):
help_text
=
"We can fill in this field based on information provided by https://peoplefinder.gmu.edu."
,
)
# The RegisteredUser's chosen organization
organization
=
CharField
(
required
=
True
,
label
=
'Organization (Required)'
,
...
...
@@ -313,7 +277,6 @@ class SignupForm(ModelForm):
help_text
=
"Or whatever
\"
group
\"
you would associate with on campus."
,
)
# The RegisteredUser's reason for signing up to us Go
description
=
CharField
(
required
=
False
,
label
=
'Description (Optional)'
,
...
...
@@ -328,16 +291,15 @@ class SignupForm(ModelForm):
# ***Need to replace lower url with production URL***
# ie. go.gmu.edu/about#terms
label
=
mark_safe
(
'Do you accept the <a href="
http://127.0.0.1:8000/about#terms
">Terms of Service</a>?'
'Do you accept the <a href="
about
">Terms of Service</a>?'
),
help_text
=
"Esssentially the GMU Responsible Use of Computing policies."
,
)
def
__init__
(
self
,
request
,
*
args
,
**
kwargs
):
"""
On initialization of the form, crispy forms renders this layout
On initialization of the form, crispy forms renders this layout
.
"""
# Necessary to call request in forms.py, is otherwise restricted to
# views.py and models.py
self
.
request
=
request
...
...
@@ -366,7 +328,6 @@ class SignupForm(ModelForm):
"""
Metadata about this ModelForm
"""
# what model this form is for
model
=
RegisteredUser
# what attributes are included
...
...
go/go/management/commands/expirelinks.py
View file @
aaaaa9ef
...
...
@@ -3,10 +3,6 @@ go/commands/expirelinks.py
Remove expired links from the database.
"""
# Future Imports
from
__future__
import
(
absolute_import
,
division
,
print_function
,
unicode_literals
)
# Django Imports
from
django.core.management.base
import
BaseCommand
from
django.utils
import
timezone
...
...
go/go/management/commands/test_expirelinks.py
View file @
aaaaa9ef
...
...
@@ -3,10 +3,6 @@ go/commands/test_expirelinks.py
Test that the function to expire Go links actually works.
"""
# Future Imports
from
__future__
import
(
absolute_import
,
division
,
print_function
,
unicode_literals
)
# Python stdlib Imports
from
datetime
import
timedelta
...
...
go/go/models.py
View file @
aaaaa9ef
"""
go/models.py
"""
# Future Imports
from
__future__
import
(
absolute_import
,
division
,
print_function
,
unicode_literals
)
The core of Go: define the business logic through classes that represent
tables containing structured data in the database.
"""
# Python stdlib Imports
import
string
...
...
@@ -16,7 +14,6 @@ from django.db import models
from
django.db.models.signals
import
post_save
from
django.dispatch
import
receiver
from
django.utils
import
timezone
from
django.utils.encoding
import
python_2_unicode_compatible
# Other Imports
from
hashids
import
Hashids
# http://hashids.org/python/
...
...
@@ -26,15 +23,13 @@ HASHIDS = Hashids(
salt
=
"srct.gmu.edu"
,
alphabet
=
(
string
.
ascii_lowercase
+
string
.
digits
)
)
@
python_2_unicode_compatible
class
RegisteredUser
(
models
.
Model
):
"""
This is simply a wrapper model for the
u
ser
object
which, if an object
This is simply a wrapper model for the
U
ser
model
which, if an object
exists, indicates that that user is registered.
"""
# Let's associate a User to this RegisteredUser
user
=
models
.
OneToOneField
(
User
)
user
=
models
.
OneToOneField
(
User
,
on_delete
=
"cascade"
)
# What is your name?
full_name
=
models
.
CharField
(
...
...
@@ -62,35 +57,29 @@ class RegisteredUser(models.Model):
def
__str__
(
self
):
"""
s
tr
(RegisteredUser)
S
tr
ing representation of this object.
"""
return
'<Registered User: %s - Approval Status: %s>'
%
(
self
.
user
,
self
.
approved
)
@
receiver
(
post_save
,
sender
=
User
)
def
handle_regUser_creation
(
sender
,
instance
,
created
,
**
kwargs
):
"""
When a post_save is called on a User object (and it is newly created), this
is called to create an associated RegisteredUser
is called to create an associated RegisteredUser
.
"""
if
created
:
RegisteredUser
.
objects
.
create
(
user
=
instance
)
@
python_2_unicode_compatible
class
URL
(
models
.
Model
):
"""
This model represents a stored URL redirection rule. Each URL has an
owner, target url, short identifier, click counter, and expiration
date.
"""
# Who is the owner of this Go link
owner
=
models
.
ForeignKey
(
RegisteredUser
)
owner
=
models
.
ForeignKey
(
RegisteredUser
,
on_delete
=
"cascade"
)
# When was this link created?
date_created
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
...
...
@@ -111,18 +100,16 @@ class URL(models.Model):
def
__str__
(
self
):
"""
print(URL)
String representation of this object.
"""
return
'<Owner: %s - Target URL: %s>'
%
(
self
.
owner
.
user
,
self
.
target
)
class
Meta
:
"""
m
eta
data for URLs
M
eta
information for this object.
"""
# they should be ordered by their short links
ordering
=
[
'short'
]
...
...
go/go/templatetags/go_extras.py
View file @
aaaaa9ef
"""
go/templatetags/go_extras.py
"""
# Future Imports
from
__future__
import
(
absolute_import
,
division
,
print_function
,
unicode_literals
)
Template functions that can be included to help out with rendering correct
data based on the status of the user.
"""
# Django Imports
from
django
import
template
...
...
@@ -20,12 +18,11 @@ register = template.Library()
@
register
.
filter
def
is_registered
(
given_user
):
"""
Helper template function to c
heck if a user is registered.
C
heck if a user is registered.
given_user: The User object that we are checking to see if they are
registered or not.
"""
# try getting the RegisteredUser of the current user
try
:
getRegisteredUser
=
RegisteredUser
.
objects
.
get
(
user
=
given_user
)
...
...
@@ -40,12 +37,11 @@ def is_registered(given_user):
@
register
.
filter
def
is_approved
(
given_user
):
"""
Helper template function to c
heck if a user is approved.
C
heck if a user is approved.
given_user: The User object that we are checking to see if they are
approved
or not.
given_user: The User object that we are checking to see if they are
approved
or not.
"""
# try getting the RegisteredUser of the current user
try
:
get_registered_user
=
RegisteredUser
.
objects
.
get
(
user
=
given_user
)
...
...
go/go/templatetags/test_go_extras.py
View file @
aaaaa9ef
"""
go/templatetags/test_go_extras.py
"""
# Future Imports
from
__future__
import
(
absolute_import
,
division
,
print_function
,
unicode_literals
)
Test the helper functions.
"""
# Django Imports
from
django.contrib.auth.models
import
User
from
django.test
import
TestCase
...
...
@@ -15,25 +12,18 @@ from go.models import RegisteredUser
from
.go_extras
import
is_approved
,
is_registered
class
GoExtrasTest
(
TestCase
):
"""
Test cases for the template helper functions in go_extras.py
"""
def
setUp
(
self
):
"""
Create a dummy user to be tested against.
"""
User
.
objects
.
create
(
username
=
'dhaynes'
,
password
=
'password'
)
# is_registered ------------------------------------------------------------
# is_registered -----------------------------------------------------------
def
test_is_registered_false
(
self
):
"""
Test the is_registered function to see if it gives correct false
answers
"""
getUser
=
User
.
objects
.
get
(
username
=
'dhaynes'
)
getRegisteredUser
=
RegisteredUser
.
objects
.
get
(
user
=
getUser
)
...
...
@@ -46,7 +36,6 @@ class GoExtrasTest(TestCase):
"""
Test the is_registered function to see if it gives correct true answers
"""
getUser
=
User
.
objects
.
get
(
username
=
'dhaynes'
)
getRegisteredUser
=
RegisteredUser
.
objects
.
get
(
user
=
getUser
)
...
...
@@ -55,13 +44,12 @@ class GoExtrasTest(TestCase):
self
.
assertTrue
(
is_registered
(
getUser
))
# is_approved --------------------------------------------------------------
# is_approved -------------------------------------------------------------
def
test_is_approved_false
(
self
):
"""
Test the is_registered function to see if it gives correct false answers
Test the is_registered function to see if it gives correct false
answers
"""
getUser
=
User
.
objects
.
get
(
username
=
'dhaynes'
)
getRegisteredUser
=
RegisteredUser
.
objects
.
get
(
user
=
getUser
)
...
...
@@ -70,12 +58,10 @@ class GoExtrasTest(TestCase):
self
.
assertFalse
(
is_approved
(
getUser
))
def
test_is_approved_true
(
self
):
"""
Test the is_registered function to see if it gives correct true answers
"""
getUser
=
User
.
objects
.
get
(
username
=
'dhaynes'
)
getRegisteredUser
=
RegisteredUser
.
objects
.
get
(
user
=
getUser
)
...
...
go/go/test_cas_callbacks.py
View file @
aaaaa9ef
# Future Imports
from
__future__
import
(
absolute_import
,
division
,
print_function
,
unicode_literals
)
"""
go/test_cas_callbacks.py
Test the CAS/PF response parsing functions.
"""
# Django Imports
from
django.test
import
TestCase
...
...
@@ -9,25 +10,19 @@ from django.test import TestCase
from
.cas_callbacks
import
pfparse
,
pfinfo
class
CasCallbacksTest
(
TestCase
):
"""
Test cases for the functions in call_callbacks.
"""
def
test_pf_peoplefinder_method
(
self
):
"""
Presently enrolled student who has been added to peoplefinder
"""
actual
=
pfinfo
(
'dhaynes3'
)
expected
=
[
'David'
,
'Haynes'
]
self
.
assertEqual
(
expected
,
actual
)
def
test_pfparse_peoplefinder_method
(
self
):
"""
Test the parsing method to ensure that first and last names are
seperated
accordingly and correctly.
Test the parsing method to ensure that first and last names are
seperated
accordingly and correctly.
"""
actual
=
pfparse
(
"Haynes, David M"
)
expected
=
[
'David'
,
'Haynes'
]
self
.
assertEqual
(
expected
,
actual
)
...
...
@@ -36,25 +31,24 @@ class CasCallbacksTest(TestCase):
"""
student no longer in peoplefinder, or who hasn't yet been added
"""
actual
=
pfinfo
(
'lfaraone'
)
expected
=
[
'Luke W'
,
'Faraone'
]
self
.
assertEqual
(
expected
,
actual
)
def
test_pfinfo_employee_method
(
self
):
"""
student employees will have their staff info return before their student info
student employees will have their staff info return before their
student info
"""
actual
=
pfinfo
(
'nander13'
)
expected
=
[
'Nicholas'
,
'Anderson'
]
self
.
assertEqual
(
expected
,
actual
)
def