Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix case sensitive url parameters #297

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,16 @@ def build_rsvps_response(events):


@app.route('/api/organizations')
@app.route('/api/organizations/<name>')
def get_organizations(name=None):
@app.route('/api/organizations/<organization_name>')
def get_organizations(organization_name=None):
''' Regular response option for organizations.
'''

filters, querystring = get_query_params(request.args)

if name:
if organization_name:
# Get one named organization.
org_filter = Organization.name == raw_name(name)
org_filter = func.lower(Organization.name) == func.lower(raw_name(organization_name))
org = db.session.query(Organization).filter(org_filter).first()
if org:
return jsonify(org.asdict(True))
Expand Down Expand Up @@ -242,7 +242,7 @@ def get_orgs_events(organization_name):
Better than /api/events?q={"filters":[{"name":"organization_name","op":"eq","val":"Code for San Francisco"}]}
'''
# Check org name
organization = Organization.query.filter_by(name=raw_name(organization_name)).first()
organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first()
if not organization:
return "Organization not found", 404

Expand All @@ -258,7 +258,7 @@ def get_upcoming_events(organization_name):
Get events that occur in the future. Order asc.
'''
# Check org name
organization = Organization.query.filter_by(name=raw_name(organization_name)).first()
organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first()
if not organization:
return "Organization not found", 404
# Get upcoming event objects
Expand All @@ -273,7 +273,7 @@ def get_past_events(organization_name):
Get events that occur in the past. Order desc.
'''
# Check org name
organization = Organization.query.filter_by(name=raw_name(organization_name)).first()
organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first()
if not organization:
return "Organization not found", 404
# Get past event objects
Expand All @@ -287,7 +287,7 @@ def get_past_events(organization_name):
def gather_orgs_rsvps(organization_name=None):
''' Orgs rsvps summarized '''
# Check org name
organization = Organization.query.filter_by(name=raw_name(organization_name)).first()
organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first()
if not organization:
return "Organization not found", 404
orgs_events = Event.query.filter(Event.organization_name == organization.name).all()
Expand All @@ -302,7 +302,7 @@ def get_orgs_stories(organization_name):
A cleaner url for getting an organizations stories
'''
# Check org name
organization = Organization.query.filter_by(name=raw_name(organization_name)).first()
organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first()
if not organization:
return "Organization not found", 404

Expand All @@ -318,7 +318,7 @@ def get_orgs_projects(organization_name):
A cleaner url for getting an organizations projects
'''
# Check org name
organization = Organization.query.filter_by(name=raw_name(organization_name)).first()
organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first()
if not organization:
return "Organization not found", 404

Expand Down Expand Up @@ -378,7 +378,7 @@ def get_orgs_issues(organization_name, labels=None):
''' A clean url to get an organizations issues
'''
# Get one named organization.
organization = Organization.query.filter_by(name=raw_name(organization_name)).first()
organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first()
if not organization:
return "Organization not found", 404

Expand Down Expand Up @@ -419,7 +419,7 @@ def get_orgs_attendance(organization_name):
''' A clean url to get an organizations attendance '''

# Get one named organization.
organization = Organization.query.filter_by(name=raw_name(organization_name)).first()
organization = db.session.query(Organization).filter(func.lower(Organization.name) == func.lower(raw_name(organization_name))).first()
if not organization:
return "Organization not found", 404

Expand Down
2 changes: 1 addition & 1 deletion test/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class AttendanceFactory(SQLAlchemyModelFactory):
FACTORY_SESSION = db.session

organization_name = factory.LazyAttribute(lambda e: OrganizationFactory().name)
organization_url = "https://www.codeforamerica.org/api/organizations/" + str(factory.LazyAttribute(lambda e: OrganizationFactory().name)).replace(" ", "-")
organization_url = u"https://www.codeforamerica.org/api/organizations/" + unicode(factory.LazyAttribute(lambda e: OrganizationFactory().name)).replace(u" ", u"-")
total = randint(1, 1000)
weekly = {
"2014 01": randint(1, 50),
Expand Down
97 changes: 95 additions & 2 deletions test/integration/test_organizations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from datetime import datetime, timedelta
import time

from test.factories import OrganizationFactory, ProjectFactory, EventFactory, StoryFactory, IssueFactory, LabelFactory
from test.factories import OrganizationFactory, ProjectFactory, EventFactory, StoryFactory, IssueFactory, LabelFactory, AttendanceFactory
from test.harness import IntegrationTest
from app import db

Expand Down Expand Up @@ -644,4 +644,97 @@ def test_geojson(self):
self.assertTrue('id' in org.keys())

# Test that only orgs with location data showed up
self.assertEqual(len(response['features']),1)
self.assertEqual(len(response['features']), 1)

def test_organization_parameters_case_insensitive(self):
''' Parameters passed via the URL should be case-insensitive.
'''
cfsf = OrganizationFactory(name=u'Code for San Francisco')
db.session.commit()

# request the organization
response = self.app.get('/api/organizations/code-for-san-francisco')
response_data = json.loads(response.data)
self.assertEqual(200, response.status_code)
self.assertTrue('name' in response_data)
self.assertEqual(u'Code for San Francisco', response_data['name'])

# add some events
EventFactory(organization_name=cfsf.name, name=u'Umoja', start_time_notz=datetime.now() - timedelta(3))
EventFactory(organization_name=cfsf.name, name=u'Kujichagulia', start_time_notz=datetime.now() - timedelta(2))
EventFactory(organization_name=cfsf.name, name=u'Ujima', start_time_notz=datetime.now() - timedelta(1))
EventFactory(organization_name=cfsf.name, name=u'Nia', start_time_notz=datetime.now() + timedelta(1))
EventFactory(organization_name=cfsf.name, name=u'Kuumba', start_time_notz=datetime.now() + timedelta(2))
db.session.commit()

# request all the organization's events
response = self.app.get('/api/organizations/code-for-san-francisco/events')
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.data)
self.assertTrue('total' in response_data)
self.assertEqual(response_data['total'], 5)

# request the organization's upcoming events
response = self.app.get('/api/organizations/code-for-san-francisco/upcoming_events')
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.data)
self.assertTrue('total' in response_data)
self.assertEqual(response_data['total'], 2)

# request the organization's past events
response = self.app.get('/api/organizations/code-for-san-francisco/past_events')
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.data)
self.assertTrue('total' in response_data)
self.assertEqual(response_data['total'], 3)

# request the organization's rsvps
response = self.app.get('/api/organizations/code-for-san-francisco/events/rsvps')
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.data)
self.assertTrue('total' in response_data)
self.assertEqual(response_data['total'], 3702)

# add a story
StoryFactory(organization_name=cfsf.name)
db.session.commit()

response = self.app.get('/api/organizations/code-for-san-francisco/stories')
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.data)
self.assertTrue('total' in response_data)
self.assertEqual(response_data['total'], 1)

# add some projects
project_mkeka = ProjectFactory(organization_name=cfsf.name, name=u'Mkeka')
project_mahindi = ProjectFactory(organization_name=cfsf.name, name=u'Mahindi')
db.session.commit()

response = self.app.get('/api/organizations/code-for-san-francisco/projects')
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.data)
self.assertTrue('total' in response_data)
self.assertEqual(response_data['total'], 2)

# add some issues
IssueFactory(project_id=project_mkeka.id, title=u'Mishumaa Saba')
IssueFactory(project_id=project_mkeka.id, title=u'Kikombe cha Umoja')
IssueFactory(project_id=project_mahindi.id, title=u'Zawadi')
db.session.commit()

response = self.app.get('/api/organizations/code-for-san-francisco/issues')
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.data)
self.assertTrue('total' in response_data)
self.assertEqual(response_data['total'], 3)

# add some attendance
AttendanceFactory(organization_name=cfsf.name)
db.session.commit()

response = self.app.get('/api/organizations/code-for-san-francisco/attendance')
self.assertEqual(response.status_code, 200)
response_data = json.loads(response.data)
self.assertTrue('total' in response_data)
self.assertTrue('organization_name' in response_data)
self.assertEqual(response_data['organization_name'], cfsf.name)