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
ef15de60
Unverified
Commit
ef15de60
authored
Mar 18, 2017
by
David Haynes
Browse files
Merge branch '2.2-dev' into 109-my-links-to-index
parents
2b95a071
da9d9ec7
Pipeline
#1101
passed with stage
in 57 seconds
Changes
21
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
.gitignore
View file @
ef15de60
...
...
@@ -15,3 +15,4 @@ venv
htmlcov/
.idea
__pycache__/
.vscode
\ No newline at end of file
LICENSE
View file @
ef15de60
Copyright 201
6
George Mason Student-Run Computing and Technology
Copyright 201
7
George Mason Student-Run Computing and Technology
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
...
...
go/go/admin.py
View file @
ef15de60
...
...
@@ -9,26 +9,29 @@ from django.contrib.auth.models import User
# App Imports
from
go.models
import
URL
,
RegisteredUser
"""
Define what attributes display in the URL Admin
"""
class
URLAdmin
(
admin
.
ModelAdmin
):
"""
Define what attributes display in the URL Admin
"""
list_display
=
(
"target"
,
"short"
,
"owner"
,
"clicks"
,
"date_created"
,
"expires"
)
# Register URLAdmin
admin
.
site
.
register
(
URL
,
URLAdmin
)
"""
Define an inline admin descriptor for User model
"""
class
RegisteredUserInline
(
admin
.
StackedInline
):
"""
Define an inline admin descriptor for User model
"""
model
=
RegisteredUser
can_delete
=
False
"""
Define a new User admin
"""
class
UserAdmin
(
UserAdmin
):
"""
Define a new User admin
"""
# see above class that we defined
inlines
=
(
RegisteredUserInline
,
)
...
...
go/go/forms.py
View file @
ef15de60
# Future Imports
from
__future__
import
unicode_literals
,
absolute_import
,
print_function
,
division
# Python stdlib Imports
from
datetime
import
date
,
datetime
,
timedelta
from
six.moves
import
urllib
# Django Imports
from
django
import
forms
from
django.core.exceptions
import
ValidationError
...
...
@@ -15,19 +19,30 @@ from crispy_forms.helper import FormHelper
from
crispy_forms.layout
import
Layout
,
Fieldset
,
Submit
,
HTML
,
Div
,
Field
from
crispy_forms.bootstrap
import
StrictButton
,
PrependedText
,
Accordion
,
AccordionGroup
from
bootstrap3_datetime.widgets
import
DateTimePicker
from
datetime
import
date
,
datetime
,
timedelta
"""
The form that is used in URL creation.
"""
class
URLForm
(
forms
.
ModelForm
):
"""
The form that is used in URL creation.
"""
# Prevent redirect loop links
def
clean_target
(
self
):
# get the entered target link
target
=
self
.
cleaned_data
.
get
(
'target'
)
# if the host (go.gmu.edu) is in the entered target link
if
self
.
host
in
target
:
try
:
final_url
=
urllib
.
request
.
urlopen
(
target
).
geturl
()
# if visiting the provided url results in an HTTP error, or redirects
# to a page that results in an HTTP error
except
urllib
.
error
.
URLError
as
e
:
# to permit users to enter sites that return most errors, but
# prevent them from entering sites that result in an HTTP 300 error
if
any
(
int
(
str
(
e
)[
11
:
14
])
==
errorNum
for
errorNum
in
range
(
300
,
308
)):
raise
ValidationError
(
"Link results in a 300 error"
)
else
:
final_url
=
""
# 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
...
...
@@ -54,12 +69,12 @@ class URLForm(forms.ModelForm):
# Custom short-url field with validators.
short
=
forms
.
SlugField
(
required
=
False
,
label
=
'Short URL (Optional)'
,
widget
=
forms
.
TextInput
(),
validators
=
[
unique_short
],
max_length
=
20
,
min_length
=
3
,
required
=
False
,
label
=
'Short URL (Optional)'
,
widget
=
forms
.
TextInput
(),
validators
=
[
unique_short
],
max_length
=
20
,
min_length
=
3
,
)
# define some string date standards
...
...
@@ -80,11 +95,11 @@ class URLForm(forms.ModelForm):
# Add preset expiration choices.
expires
=
forms
.
ChoiceField
(
required
=
True
,
label
=
'Expiration (Required)'
,
choices
=
EXPIRATION_CHOICES
,
initial
=
NEVER
,
widget
=
forms
.
RadioSelect
(),
required
=
True
,
label
=
'Expiration (Required)'
,
choices
=
EXPIRATION_CHOICES
,
initial
=
NEVER
,
widget
=
forms
.
RadioSelect
(),
)
# Check if the selected date is a valid date
...
...
@@ -99,12 +114,12 @@ class URLForm(forms.ModelForm):
# Add a custom expiration choice.
expires_custom
=
forms
.
DateTimeField
(
required
=
False
,
label
=
'Custom Date'
,
input_formats
=
[
'%m-%d-%Y'
],
validators
=
[
valid_date
],
initial
=
lambda
:
datetime
.
now
()
+
timedelta
(
days
=
1
),
widget
=
DateTimePicker
(
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
,
...
...
@@ -141,9 +156,9 @@ class URLForm(forms.ModelForm):
<h4>Paste the URL you would like to shorten:</h4>
<br />"""
),
'target'
,
style
=
"background: rgb(#F6F6F6);"
),
active
=
True
,
template
=
'crispy/accordian-group.html'
),
style
=
"background: rgb(#F6F6F6);"
),
active
=
True
,
template
=
'crispy/accordian-group.html'
),
# Step 2: Short URL
AccordionGroup
(
'Step 2: Short URL'
,
...
...
@@ -153,9 +168,9 @@ class URLForm(forms.ModelForm):
<br />"""
),
PrependedText
(
'short'
,
'https://go.gmu.edu/'
,
template
=
'crispy/customPrepended.html'
),
style
=
"background: rgb(#F6F6F6);"
),
active
=
True
,
template
=
'crispy/accordian-group.html'
,),
style
=
"background: rgb(#F6F6F6);"
),
active
=
True
,
template
=
'crispy/accordian-group.html'
,),
# Step 3: Expiration
AccordionGroup
(
'Step 3: URL Expiration'
,
...
...
@@ -165,12 +180,12 @@ class URLForm(forms.ModelForm):
<br />"""
),
'expires'
,
Field
(
'expires_custom'
,
template
=
"crispy/customDateField.html"
),
style
=
"background: rgb(#F6F6F6);"
),
active
=
True
,
template
=
'crispy/accordian-group.html'
),
style
=
"background: rgb(#F6F6F6);"
),
active
=
True
,
template
=
'crispy/accordian-group.html'
),
# FIN
template
=
'crispy/accordian.html'
),
# FIN
template
=
'crispy/accordian.html'
),
#######################
HTML
(
"""
<br />"""
),
...
...
@@ -181,42 +196,44 @@ class URLForm(forms.ModelForm):
# what model this form is for
model
=
URL
# what attributes are included
fields
=
[
'target'
,
]
fields
=
[
'target'
]
"""
The form that is used when a user is signing up to be a RegisteredUser
"""
class
SignupForm
(
forms
.
ModelForm
):
"""
The form that is used when a user is signing up to be a RegisteredUser
"""
# The full name of the RegisteredUser
full_name
=
forms
.
CharField
(
required
=
True
,
label
=
'Full Name (Required)'
,
max_length
=
100
,
widget
=
forms
.
TextInput
(),
required
=
True
,
label
=
'Full Name (Required)'
,
max_length
=
100
,
widget
=
forms
.
TextInput
(),
)
# The RegisteredUser's chosen organization
organization
=
forms
.
CharField
(
required
=
True
,
label
=
'Organization (Required)'
,
max_length
=
100
,
widget
=
forms
.
TextInput
(),
required
=
True
,
label
=
'Organization (Required)'
,
max_length
=
100
,
widget
=
forms
.
TextInput
(),
)
# The RegisteredUser's reason for signing up to us Go
description
=
forms
.
CharField
(
required
=
False
,
label
=
'Description (Optional)'
,
max_length
=
200
,
widget
=
forms
.
Textarea
(),
required
=
False
,
label
=
'Description (Optional)'
,
max_length
=
200
,
widget
=
forms
.
Textarea
(),
)
# A user becomes registered when they agree to the TOS
registered
=
forms
.
BooleanField
(
required
=
True
,
# ***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>?'
),
label
=
mark_safe
(
'Do you accept the <a href="http://127.0.0.1:8000/about#terms">Terms of Service</a>?'
),
)
# on initialization of the form, crispy forms renders this layout
...
...
@@ -249,4 +266,4 @@ class SignupForm(forms.ModelForm):
# what model this form is for
model
=
RegisteredUser
# what attributes are included
fields
=
[
'full_name'
,
'organization'
,
'description'
,
'registered'
,
]
fields
=
[
'full_name'
,
'organization'
,
'description'
,
'registered'
]
go/go/management/commands/expirelinks.py
View file @
ef15de60
...
...
@@ -10,6 +10,10 @@ from go.models import URL
# Define a new custom django-admin command
class
Command
(
BaseCommand
):
"""
Remove expired links from the database
"""
# Define help text for this command
help
=
'Removes expired links from the database'
...
...
go/go/management/commands/test_expirelinks.py
View file @
ef15de60
...
...
@@ -7,14 +7,15 @@ 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
Test cases for the functions in expirelinks
"""
def
test_Django_Test
(
self
):
"""
Default test case, does not actually test anything
"""
self
.
assertEqual
(
"Hello World!"
,
"Hello World!"
)
go/go/models.py
View file @
ef15de60
# Future Imports
from
__future__
import
unicode_literals
,
absolute_import
,
print_function
,
division
# Python stdlib Imports
import
string
# Django Imports
from
django.db
import
models
from
django.contrib.auth.models
import
User
...
...
@@ -12,46 +15,45 @@ from django.utils.encoding import python_2_unicode_compatible
# Other Imports
from
hashids
import
Hashids
# http://hashids.org/python/
import
string
# generate the salt and initialize Hashids
hashids
=
Hashids
(
salt
=
"srct.gmu.edu"
,
alphabet
=
(
string
.
ascii_lowercase
+
string
.
digits
))
"""
This is simply a wrapper model for the user object which, if an object
exists, indicates that that user is registered.
"""
@
python_2_unicode_compatible
class
RegisteredUser
(
models
.
Model
):
# Is this User Blocked?
blocked
=
models
.
BooleanField
(
default
=
False
)
"""
This is simply a wrapper model for the user object which, if an object
exists, indicates that that user is registered.
"""
# Let's associate a User to this RegisteredUser
user
=
models
.
OneToOneField
(
User
)
# What is your name?
full_name
=
models
.
CharField
(
blank
=
False
,
max_length
=
100
,
blank
=
False
,
max_length
=
100
,
)
# What organization are you associated with?
organization
=
models
.
CharField
(
blank
=
False
,
max_length
=
100
,
blank
=
False
,
max_length
=
100
,
)
# Why do you want to use Go?
description
=
models
.
TextField
(
blank
=
True
)
description
=
models
.
TextField
(
blank
=
True
)
# Have you filled out the registration form?
registered
=
models
.
BooleanField
(
default
=
False
)
registered
=
models
.
BooleanField
(
default
=
False
)
# Are you approved to use Go?
approved
=
models
.
BooleanField
(
default
=
False
)
approved
=
models
.
BooleanField
(
default
=
False
)
# Is this User Blocked?
blocked
=
models
.
BooleanField
(
default
=
False
)
#
print
(RegisteredUser)
#
str
(RegisteredUser)
def
__str__
(
self
):
return
'<Registered User: %s - Approval Status: %s>'
%
(
self
.
user
,
self
.
approved
)
...
...
@@ -64,37 +66,37 @@ def handle_regUser_creation(sender, instance, created, **kwargs):
RegisteredUser
.
objects
.
create
(
user
=
instance
)
"""
This model represents a stored URL redirection rule. Each URL has an
owner, target url, short identifier, click counter, and expiration
date.
"""
@
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
)
# When was this link created?
date_created
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
date_created
=
models
.
DateTimeField
(
default
=
timezone
.
now
)
# What is the target URL for this Go link
target
=
models
.
URLField
(
max_length
=
1000
)
target
=
models
.
URLField
(
max_length
=
1000
)
# What is the actual go link (short url) for this URL
short
=
models
.
SlugField
(
max_length
=
20
,
primary_key
=
True
)
short
=
models
.
SlugField
(
max_length
=
20
,
primary_key
=
True
)
# how many people have visited this Go link
clicks
=
models
.
IntegerField
(
default
=
0
)
clicks
=
models
.
IntegerField
(
default
=
0
)
# how many people have visited this Go link through the qr code
qrclicks
=
models
.
IntegerField
(
default
=
0
)
qrclicks
=
models
.
IntegerField
(
default
=
0
)
# how many people have visited the go link through social media
socialclicks
=
models
.
IntegerField
(
default
=
0
)
socialclicks
=
models
.
IntegerField
(
default
=
0
)
# does this Go link expire on a certain date
expires
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
)
expires
=
models
.
DateTimeField
(
blank
=
True
,
null
=
True
)
# print(URL)
def
__str__
(
self
):
return
'<
%s
: %s>'
%
(
self
.
owner
.
user
,
self
.
target
)
return
'<
Owner: %s - Target URL
: %s>'
%
(
self
.
owner
.
user
,
self
.
target
)
# metadata for URL's
class
Meta
:
...
...
go/go/templates/admin/useradmin.html
View file @
ef15de60
This diff is collapsed.
Click to expand it.
go/go/templatetags/go_extras.py
View file @
ef15de60
...
...
@@ -12,17 +12,18 @@ from go.models import RegisteredUser
# filters are registered.
register
=
template
.
Library
()
"""
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
(
givenUser
):
def
is_registered
(
given_user
):
"""
Helper template function to check 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
U
ser
)
getRegisteredUser
=
RegisteredUser
.
objects
.
get
(
user
=
given
_u
ser
)
# if it works then the user is registered
return
getRegisteredUser
.
registered
# This should never happen
...
...
@@ -31,19 +32,20 @@ def is_registered(givenUser):
# if they don't exist then they are not registered
return
False
"""
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
(
givenUser
):
def
is_approved
(
given_user
):
"""
Helper template function to check if a user is approved.
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
R
egistered
U
ser
=
RegisteredUser
.
objects
.
get
(
user
=
given
U
ser
)
get
_r
egistered
_u
ser
=
RegisteredUser
.
objects
.
get
(
user
=
given
_u
ser
)
# if they exist, return whether or not they are approved (boolean)
return
get
R
egistered
U
ser
.
approved
return
get
_r
egistered
_u
ser
.
approved
# This should never happen
except
RegisteredUser
.
DoesNotExist
as
ex
:
print
(
ex
)
...
...
go/go/templatetags/test_go_extras.py
View file @
ef15de60
...
...
@@ -9,22 +9,25 @@ from django.contrib.auth.models import User
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.
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'
)
"""
Test the is_registered function to see if it gives correct false answers
"""
def
test_is_registeredFalse
(
self
):
# 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
)
...
...
@@ -33,10 +36,11 @@ class GoExtrasTest(TestCase):
self
.
assertFalse
(
is_registered
(
getUser
))
"""
Test the is_registered function to see if it gives correct true answers
"""
def
test_is_registeredTrue
(
self
):
def
test_is_registered_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
)
...
...
@@ -45,10 +49,13 @@ class GoExtrasTest(TestCase):
self
.
assertTrue
(
is_registered
(
getUser
))
"""
Test the is_registered function to see if it gives correct false answers
"""
def
test_is_approvedFalse
(
self
):
# is_approved --------------------------------------------------------------
def
test_is_approved_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
)
...
...
@@ -58,10 +65,11 @@ class GoExtrasTest(TestCase):
self
.
assertFalse
(
is_approved
(
getUser
))
"""
Test the is_registered function to see if it gives correct true answers
"""
def
test_is_approvedTrue
(
self
):
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 @
ef15de60
...
...
@@ -7,48 +7,54 @@ 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
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
)
"""
Test the parsing method to ensure that first and last names are seperated
accordingly and correctly.
"""
def
test_pfparse_peoplefinder_method
(
self
):
"""
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
)
"""
student no longer in peoplefinder, or who hasn't yet been added
"""
def
test_pfinfo_ldap_method
(
self
):
"""
student no longer in peoplefinder, or who hasn't yet been added
"""
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
):
"""
student employees will have their staff info return before their student info
"""
actual
=
pfinfo
(
'nander13'
)
expected
=
[
'Nicholas'
,
'Anderson'
]
self
.
assertEqual
(
expected
,
actual
)
"""