Skip to content

Commit

Permalink
diff short code for http and non http fix, clickmeta test case, fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
amitt001 committed Nov 25, 2017
1 parent 32c3933 commit 23f4032
Show file tree
Hide file tree
Showing 11 changed files with 85 additions and 22 deletions.
5 changes: 0 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
appdirs==1.4.3
appnope==0.1.0
bcrypt==3.1.4
certifi==2017.11.5
Expand All @@ -7,12 +6,10 @@ chardet==3.0.4
click==6.7
decorator==4.1.2
Django==1.11.7
ecdsa==0.13
Flask==0.12.2
Flask-Cors==3.0.3
Flask-JWT-Extended==3.3.4
Flask-Script==2.0.6
future==0.16.0
geoip2==2.6.0
idna==2.6
ipython==6.2.1
Expand All @@ -30,10 +27,8 @@ pickleshare==0.7.4
prompt-toolkit==1.0.15
ptyprocess==0.5.2
pycparser==2.18
pycrypto==2.6.1
Pygments==2.2.0
PyJWT==1.5.3
pyparsing==2.2.0
pytest==3.2.5
pytz==2017.3
requests==2.18.4
Expand Down
10 changes: 7 additions & 3 deletions src/pygmy/app/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def shorten(long_url, short_code=None, expire_after=None, description=None,
query_dict.update(dict(short_code=short_code, is_custom=True))
insert_dict = query_dict
if secret_key:
query_dict.update(secret_key=secret_key, is_protected=True)
query_dict.update(secret_key=str(secret_key), is_protected=True)
insert_dict = query_dict
if expire_after:
insert_dict['expire_after'] = expire_after
Expand Down Expand Up @@ -71,7 +71,7 @@ def unshorten(short_url, secret_key=None,
if url_manager.has_expired():
raise LinkExpired
if link.is_protected:
if not secret_key or link.secret_key != secret_key:
if not secret_key or str(link.secret_key) != str(secret_key):
raise URLAuthFailed(short_url)
if request:
save_clickmeta(request, link)
Expand All @@ -93,7 +93,7 @@ def resolve_short(short_code, request=None, secret_key=None):
if manager.has_expired() is True:
raise LinkExpired('Link has expired')
if link.is_protected:
if not secret_key or link.secret_key != secret_key:
if not secret_key or str(link.secret_key) != str(secret_key):
raise URLAuthFailed(short_code)
# put stats
if request:
Expand Down Expand Up @@ -147,3 +147,7 @@ def save_clickmeta(request, link):
else:
data = parse_request(request)
return ClickMetaManager().add(link_id=link.id, **data)


def click(short_code):
"""Add method to mimic click url"""
3 changes: 2 additions & 1 deletion src/pygmy/config/pygmy.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ host = 0.0.0.0
port = 9119
debug = False
flask_secret = CvJHGFVBj*&^TRGBHDdBV836bdy73JJDHGV
url = 127.0.0.1
short_url = 127.0.0.1
short_url_schema = http://

[database]
file_name: pygmy.db
Expand Down
3 changes: 1 addition & 2 deletions src/pygmy/exception/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ def __init__(self, url):
self.url = url

def __str__(self):
return ("Invalid/missing secret key for"
" protected url {0}.").format(self.url)
return "Invalid/missing secret key for protected url"
16 changes: 13 additions & 3 deletions src/pygmy/model/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from sqlalchemy.orm import relationship
from sqlalchemy import (Column, String, Integer, Boolean,
BigInteger, Unicode, DateTime)
from urllib.parse import urlparse

from pygmy.database.base import Model
from pygmy.database.dbutil import dbconnection, utcnow
Expand Down Expand Up @@ -142,6 +143,8 @@ def has_expired(self):

@staticmethod
def crc32(long_url):
if not urlparse(long_url).scheme:
long_url = 'http://{}'.format(long_url)
return binascii.crc32(str.encode(long_url))

@property
Expand All @@ -155,6 +158,8 @@ def add(self, db, long_url, **kwargs):
if db.bind.name == 'mysql':
kwargs['created_at'] = datetime.datetime.utcnow()
kwargs['updated_at'] = datetime.datetime.utcnow()
if not urlparse(long_url).scheme:
long_url = 'http://{}'.format(long_url)
self.link = Link(long_url=long_url,
long_url_hash=self.crc32(long_url), **kwargs)
db.add(self.link)
Expand All @@ -180,6 +185,8 @@ def update(self, db, **kwargs):

@dbconnection
def get(self, db, long_url, is_default=True):
if not urlparse(long_url).scheme:
long_url = 'http://{}'.format(long_url)
query_dict = dict(long_url_hash=self.crc32(long_url),
long_url=long_url,
is_default=is_default)
Expand Down Expand Up @@ -246,9 +253,12 @@ def find(self, db, **kwargs):
long_url query for performance optimization.
"""
query_dict = dict()
if kwargs.get('long_url'):
query_dict['long_url_hash'] = self.crc32(kwargs.get('long_url'))
query_dict['long_url'] = kwargs.get('long_url')
long_url = kwargs.get('long_url')
if long_url:
if not urlparse(long_url).scheme:
long_url = 'http://{}'.format(long_url)
query_dict['long_url_hash'] = self.crc32(long_url)
query_dict['long_url'] = long_url
query_dict.update(self.build_query_dict(**kwargs))
# build sqlalchmey and query
query = [getattr(Link, k) == v for k, v in query_dict.items()]
Expand Down
3 changes: 2 additions & 1 deletion src/pygmy/tests/pygmy_test.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ host = 0.0.0.0
port = 9118
debug = False
flask_secret = CvJHGFVBj*&^TRGBHDdBV836bdy73JJDHGV
url = 127.0.0.1
short_url = 127.0.0.1
short_url_schema = http://

[database]
file_name: pygmy_test.db
Expand Down
36 changes: 36 additions & 0 deletions src/pygmy/tests/test_click_stats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os
import tempfile
from unittest import TestCase

from pygmy.app.link import shorten, unshorten, link_stats
from pygmy.core.initialize import initialize_test
from pygmy.config import config


class URLClickStatsTest(TestCase):
"""Test for clickmeta i.e. click stats"""

DBPath = None

def setUp(self):
self.long_url = 'https://example.com'

@classmethod
def setUpClass(cls):
currdir = os.path.dirname(os.path.abspath(__file__))
config_path = currdir + '/pygmy_test.cfg'
db_path = tempfile.NamedTemporaryFile(suffix='.db').name
cls.DBPath = "sqlite:///{}".format(db_path)
initialize_test(config_path, db_url=cls.DBPath)

def test_config(self):
assert config is not None
assert config.db is not None
assert self.DBPath is not None

def test_clickmeta(self):
data = shorten(self.long_url)
assert isinstance(data, dict) is True
assert link_stats(data['short_code'] + 'abc+') is None
stats = link_stats(data['short_code'] + '+')
assert stats is not None
22 changes: 18 additions & 4 deletions src/pygmy/tests/test_url_shorten_unshorten.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pygmy.core.initialize import initialize_test
from pygmy.app.link import shorten, unshorten
from pygmy.config import config
from pygmy.exception.auth import URLAuthFailed


class URLShortenUnshortenTestCases(TestCase):
Expand All @@ -13,7 +14,7 @@ class URLShortenUnshortenTestCases(TestCase):
DBPath = None

def setUp(self):
self.long_url = 'https://github.com'
self.long_url = 'https://example.com'

@classmethod
def setUpClass(cls):
Expand All @@ -28,7 +29,7 @@ def test_config(self):
assert config.db is not None
assert self.DBPath is not None

def test_long_url_shorten(self):
def test_aaa_long_url_shorten(self):
data = shorten(self.long_url)
assert isinstance(data, dict) is True
assert data['short_code'] == 'b'
Expand All @@ -45,13 +46,26 @@ def test_custom_short_url(self):
assert udata['long_url'] == self.long_url

def test_secret_short_url(self):
secret_key = 'safe'
secret_key = 123
data = shorten(self.long_url, secret_key=secret_key)
assert data['is_protected'] is True
assert data['secret_key'] == secret_key
assert data['secret_key'] == str(secret_key)
with self.assertRaises(URLAuthFailed):
unshorten(data['short_code'])
unshorten(data['short_code'], secret_key='safe')
udata = unshorten(data['short_code'], secret_key='123')
assert udata['long_url'] == data['long_url']

def test_short_url_unshorten(self):
data = shorten(self.long_url)
udata = unshorten(data['short_code'])
assert isinstance(udata, dict)
assert udata['long_url'] == self.long_url

def test_http_non_http_url(self):
urls = [
'http://example.com',
'example.com'
]
response = set(shorten(u)['short_code'] for u in urls)
assert len(response) == 1
5 changes: 4 additions & 1 deletion src/pygmy/utilities/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ def validate_url(url):


def make_short_url(short_path):
short_url = urljoin(config.pygmy['url'], short_path)
short_url = urljoin(
config.pygmy['short_url_schema'],
config.pygmy['short_url'],
short_path)
return short_url


Expand Down
2 changes: 1 addition & 1 deletion src/pygmy/validator/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class LinkSchema(Schema):
short_code = fields.Str(required=False,
allow_none=True,
validate=is_valid_custom_code_or_secret)
short_url = fields.Method('short_url_path', load_only=True)
short_url = fields.Method('short_url_path', dump_only=True)
description = fields.Str(required=False, allow_none=True)
secret_key = fields.Str(required=False,
allow_none=True,
Expand Down
2 changes: 1 addition & 1 deletion src/pyui/restclient/pygmy.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def list_links(self, access_token):
raise ObjectNotFound(resp_obj)
links = resp_obj
for link in links:
if link.get('short_url'):
if link.get('short_code'):
link['short_url'] = self.HOSTNAME + '/' + link['short_code']
return links

Expand Down

0 comments on commit 23f4032

Please sign in to comment.