Commit 0241bf35 authored by David Haynes's avatar David Haynes 🙆

Add validators for short

- unique and valid shorts are only used
parent b63d7963
...@@ -10,9 +10,9 @@ from django.contrib.auth.models import User ...@@ -10,9 +10,9 @@ from django.contrib.auth.models import User
# Other Imports # Other Imports
import requests import requests
def pfparse(pf_name_result): def pfparse(pf_name_result: str) -> list:
""" """
Parse what peoplefinder sends back to us and make a list out of it Parse what peoplefinder sends back to us and make a list out of it.
""" """
# name comes in format of Anderson, Nicholas J # name comes in format of Anderson, Nicholas J
name_list = pf_name_result.split(',') name_list = pf_name_result.split(',')
...@@ -29,12 +29,11 @@ def pfparse(pf_name_result): ...@@ -29,12 +29,11 @@ def pfparse(pf_name_result):
new_name_list = [first_name, name_list[0]] new_name_list = [first_name, name_list[0]]
return new_name_list return new_name_list
def pfinfo(uname): def pfinfo(uname: str) -> list:
""" """
Get information from peoplefinder Get information from peoplefinder.
""" """
base_url = settings.PF_URL url = f"{settings.PF_URL}basic/all/{uname}"
url = base_url + "basic/all/" + str(uname)
try: try:
metadata = requests.get(url, timeout=30) metadata = requests.get(url, timeout=30)
print("Retrieving information from the peoplefinder api.") print("Retrieving information from the peoplefinder api.")
...@@ -73,7 +72,7 @@ def pfinfo(uname): ...@@ -73,7 +72,7 @@ def pfinfo(uname):
print("Returning empty user info tuple.") print("Returning empty user info tuple.")
return ['', ''] return ['', '']
def create_user(tree): def create_user(tree: list):
""" """
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.
""" """
......
...@@ -9,8 +9,8 @@ from datetime import datetime, timedelta ...@@ -9,8 +9,8 @@ from datetime import datetime, timedelta
# Django Imports # Django Imports
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms import (BooleanField, CharField, ChoiceField, DateTimeField, from django.forms import (BooleanField, CharField, ChoiceField, DateTimeField,
ModelForm, RadioSelect, SlugField, Textarea, ModelForm, RadioSelect, Textarea, TextInput,
TextInput, URLField, URLInput) URLField, URLInput)
from django.utils import timezone from django.utils import timezone
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
...@@ -41,25 +41,10 @@ class URLForm(ModelForm): ...@@ -41,25 +41,10 @@ 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.')
short = CharField( short = CharField(
required=False, required=False,
label='Short URL (Optional)', label='Short URL (Optional)',
widget=TextInput(), widget=TextInput(),
validators=[unique_short],
max_length=20, max_length=20,
min_length=1, min_length=1,
) )
......
# Generated by Django 2.0.5 on 2018-06-03 23:40
from django.db import migrations, models
import go.models
class Migration(migrations.Migration):
dependencies = [
('go', '0003_auto_20180524_0003'),
]
operations = [
migrations.AlterField(
model_name='url',
name='destination',
field=models.URLField(default='https://go.gmu.edu', help_text='The URL to be redirected to when visiting the shortlink.', max_length=1000),
),
migrations.AlterField(
model_name='url',
name='short',
field=models.CharField(help_text='The shortcode that acts as the unique go link.', max_length=20, unique=True, validators=[go.models.URL.unique_short_validator, go.models.URL.regex_short_validator]),
),
]
...@@ -6,6 +6,7 @@ tables containing structured data in the database. ...@@ -6,6 +6,7 @@ tables containing structured data in the database.
""" """
# Python stdlib Imports # Python stdlib Imports
import string import string
import re
# Django Imports # Django Imports
from django.contrib.auth.models import User from django.contrib.auth.models import User
...@@ -14,6 +15,7 @@ from django.db import models ...@@ -14,6 +15,7 @@ from django.db import models
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from django.utils import timezone from django.utils import timezone
from django.core.exceptions import ValidationError
# Other Imports # Other Imports
from hashids import Hashids from hashids import Hashids
...@@ -144,20 +146,38 @@ class URL(models.Model): ...@@ -144,20 +146,38 @@ class URL(models.Model):
destination = models.URLField( destination = models.URLField(
max_length=1000, max_length=1000,
default="https://go.gmu.edu", default="https://go.gmu.edu",
help_text="" help_text="The URL to be redirected to when visiting the shortlink."
) )
# TODO Validator for Slug + Emoji def unique_short_validator(value):
""" """
# http://stackoverflow.com/a/13752628/6762004 Check to make sure the short url has not been used
RE_EMOJI = re.compile('[\U00010000-\U0010ffff]', flags=re.UNICODE) """
slug_unicode_re = _lazy_re_compile(r'^[-\w]+\Z') try:
slug_re = _lazy_re_compile(r'^[-a-zA-Z0-9_]+\Z') # if we're able to get a URL with the same short url
""" URL.objects.get(short__iexact=value)
raise ValidationError(f"Short url already exists.")
except URL.DoesNotExist as ex:
print(ex)
return
def regex_short_validator(value):
"""
Run the short through our regex validation before insertion into the
database.
"""
# http://stackoverflow.com/a/13752628/6762004
re_emoji = re.compile('^(([\U00010000-\U0010ffff][\U0000200D]?)+)$')
re_str = re.compile('^([-\w]+)$')
if not re_emoji.match(value) and not re_str.match(value):
raise ValidationError(f"Short url fails regex check.")
# Note: min_length cannot exist on a model so it is enforced in forms.py
short = models.CharField( short = models.CharField(
max_length=20, max_length=20,
unique=True, unique=True,
help_text="" validators=[unique_short_validator, regex_short_validator],
help_text="The shortcode that acts as the unique go link."
) )
# TODO Abstract analytics into their own model # TODO Abstract analytics into their own model
...@@ -166,9 +186,7 @@ class URL(models.Model): ...@@ -166,9 +186,7 @@ class URL(models.Model):
socialclicks = models.IntegerField(default=0, help_text="") socialclicks = models.IntegerField(default=0, help_text="")
def __str__(self): def __str__(self):
return '<Owner: %s - destination URL: %s>' % ( return f"<Owner: {self.owner.user} - destination URL: {self.destination}>"
self.owner.user, self.destination
)
class Meta: class Meta:
ordering = ['short'] ordering = ['short']
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment