Skip to content

Commit

Permalink
Revert "Revert "Merge pull request #62 from hpincket/master""
Browse files Browse the repository at this point in the history
In which harrison reverts joe's revert so that the merge is better.

This reverts commit ee7b1dd.
  • Loading branch information
hpincket committed Sep 20, 2016
1 parent ee7b1dd commit a1a8fca
Show file tree
Hide file tree
Showing 21 changed files with 370 additions and 345 deletions.
3 changes: 3 additions & 0 deletions .flake8
@@ -0,0 +1,3 @@
[flake8]
ignore=E501
exclude=venv,env
8 changes: 8 additions & 0 deletions .travis.yml
@@ -0,0 +1,8 @@
language: python
python:
- "3.4"
install:
- pip install flake8
- pip install -r requirements.txt
script:
- flake8 .
21 changes: 11 additions & 10 deletions api/__init__.py
Expand Up @@ -4,6 +4,11 @@
from functools import wraps from functools import wraps
import pymongo import pymongo
import os import os
import api.meta
import api.dining
import api.wifi
import api.laundry
import api.courses




def make_json_error(ex): def make_json_error(ex):
Expand All @@ -28,7 +33,6 @@ def support_jsonp(f):
def decorated_function(*args, **kwargs): def decorated_function(*args, **kwargs):
callback = request.args.get('callback', False) callback = request.args.get('callback', False)
if callback: if callback:
from json import dumps
content = callback.encode("utf-8") + b'(' + f(*args, **kwargs).data + b')' content = callback.encode("utf-8") + b'(' + f(*args, **kwargs).data + b')'
return current_app.response_class( return current_app.response_class(
content, mimetype='application/javascript') content, mimetype='application/javascript')
Expand Down Expand Up @@ -79,6 +83,7 @@ def __init__(self, environ, populate_request=True, shallow=False):


# BASIC AUTH # BASIC AUTH



def check_auth(username, password): def check_auth(username, password):
"""This function is called to check if a username / """This function is called to check if a username /
password combination is valid. password combination is valid.
Expand All @@ -91,12 +96,14 @@ def check_auth(username, password):
print("The dashboard password's environment variable was not found.") print("The dashboard password's environment variable was not found.")
return username == 'admin' and password == correct_password return username == 'admin' and password == correct_password



def authenticate(): def authenticate():
"""Sends a 401 response that enables basic auth""" """Sends a 401 response that enables basic auth"""
return Response( return Response(
'Could not verify your access level for that URL.\n' 'Could not verify your access level for that URL.\n'
'You have to login with proper credentials', 401, 'You have to login with proper credentials', 401,
{'WWW-Authenticate': 'Basic realm="Login Required"'}) {'WWW-Authenticate': 'Basic realm="Login Required"'})



def requires_auth(f): def requires_auth(f):
@wraps(f) @wraps(f)
Expand All @@ -108,10 +115,4 @@ def decorated(*args, **kwargs):
return decorated return decorated




import api.meta
import api.dining
import api.wifi
import api.laundry
import api.courses

__all__ = ['api', ] __all__ = ['api', ]
36 changes: 15 additions & 21 deletions api/courses.py
@@ -1,12 +1,10 @@
from flask import request, jsonify from flask import request, jsonify
from api import app, make_json_error, support_jsonp from api import app, make_json_error, support_jsonp
from api.meta import is_valid_client, require_client_id, log_client, INVALID_CLIENT_MSG from api.meta import require_client_id
from mongoengine import connect from mongoengine import connect
import json import json
import urllib import urllib
from collections import defaultdict from api.scripts.coursemodels import BannerCourse, NonconflictEntry
import random
from api.scripts.coursemodels import *
import bson import bson
from datetime import date from datetime import date
import os import os
Expand All @@ -16,7 +14,7 @@
PAGINATION_LIMIT = 10 PAGINATION_LIMIT = 10
PAGINATION_MAX = 42 PAGINATION_MAX = 42


#TODO: Maybe there's some way to use the same connection as given by 'db'. # TODO: Maybe there's some way to use the same connection as given by 'db'.


if 'MONGO_URI' in app.config: if 'MONGO_URI' in app.config:
connect('brown', host=app.config['MONGO_URI']) connect('brown', host=app.config['MONGO_URI'])
Expand All @@ -35,7 +33,7 @@ def courses_index():
or or
Returns the sections ids specified Returns the sections ids specified
''' '''
arg_numbers = request.args.get('numbers',None) arg_numbers = request.args.get('numbers', None)
if arg_numbers is not None: if arg_numbers is not None:
numbers = [] numbers = []
full_numbers = [] full_numbers = []
Expand Down Expand Up @@ -119,9 +117,9 @@ def schedule_time():
time = int(request.args.get('time', '-1')) time = int(request.args.get('time', '-1'))
if time < 0: if time < 0:
return make_json_error("Invalid or Missing parameter: time") return make_json_error("Invalid or Missing parameter: time")
query_args = {'meeting.day_of_week':day, query_args = {'meeting.day_of_week': day,
"meeting.start_time": {'$lte': time}, 'meeting.start_time': {'$lte': time},
"meeting.end_time": {'$gte': time}} 'meeting.end_time': {'$gte': time}}
return jsonify(paginate(filter_semester(query_args), params={'day': day, 'time': time}, raw=True)) return jsonify(paginate(filter_semester(query_args), params={'day': day, 'time': time}, raw=True))




Expand All @@ -136,21 +134,16 @@ def non_conflicting():
for course_number in courses: for course_number in courses:
res = BannerCourse.objects(full_number=course_number) res = BannerCourse.objects(full_number=course_number)
if len(res) <= 0: if len(res) <= 0:
return make_json_error(\ return make_json_error("Invalid course section/lab/conference:" + course_number)
"Invalid course section/lab/conference:"\
+course_number)
course = res.first().id course = res.first().id
non_conflicting_list = NonconflictEntry.objects(course_id=course) non_conflicting_list = NonconflictEntry.objects(course_id=course)
if len(non_conflicting_list) <= 0: if len(non_conflicting_list) <= 0:
return make_json_error(\ return make_json_error("Error with course section/lab/conference:" + course_number)
"Error with course section/lab/conference:"\
+course_number)
non_conflicting_list = non_conflicting_list.first().non_conflicting non_conflicting_list = non_conflicting_list.first().non_conflicting
if available_set is None: if available_set is None:
available_set = set(non_conflicting_list) available_set = set(non_conflicting_list)
else: else:
available_set = set.intersection(available_set, available_set = set.intersection(available_set, non_conflicting_list)
non_conflicting_list)
query_args = {"id__in": list(available_set)} query_args = {"id__in": list(available_set)}
else: else:
# Slower method, a couple of seconds # Slower method, a couple of seconds
Expand Down Expand Up @@ -192,19 +185,20 @@ def paginate(query, params=None, raw=False):
if '_id' not in query: if '_id' not in query:
query['_id'] = {} query['_id'] = {}
query['_id']['$gt'] = bson.objectid.ObjectId(offset) query['_id']['$gt'] = bson.objectid.ObjectId(offset)
res = list(BannerCourse.objects(__raw__=query).order_by('_id')[:limit+1]) res = list(BannerCourse.objects(__raw__=query).order_by('_id')[:limit + 1])
next_url = "null" next_url = "null"
if len(res) == limit+1: if len(res) == limit + 1:
next_url = request.base_url + "?" +\ next_url = request.base_url + "?" +\
urllib.parse.urlencode({"limit": limit, urllib.parse.urlencode({"limit": limit,
"offset": res[limit - 1].id}) "offset": res[limit - 1].id})
client_id = request.args.get('client_id') client_id = request.args.get('client_id')
next_url = next_url + "&" + urllib.parse.urlencode({"client_id": client_id}) next_url = next_url + "&" + urllib.parse.urlencode({"client_id": client_id})
if params is not None: if params is not None:
next_url = next_url+"&"+urllib.parse.urlencode(params) next_url = next_url + "&" + urllib.parse.urlencode(params)
res.pop() res.pop()


if offset is None: offset = "null" if offset is None:
offset = "null"
ans = {"href": request.url, ans = {"href": request.url,
"items": [json.loads(elm.to_json()) for elm in res], "items": [json.loads(elm.to_json()) for elm in res],
"limit": limit, "limit": limit,
Expand Down
15 changes: 9 additions & 6 deletions api/forms.py
Expand Up @@ -7,12 +7,13 @@
from api.scripts.add_documentation import add_documentation from api.scripts.add_documentation import add_documentation
from api.scripts.add_member import add_member from api.scripts.add_member import add_member



class SignupForm(Form): class SignupForm(Form):
name = StringField('Name', validators=[DataRequired()]) name = StringField('Name', validators=[DataRequired()])
email = EmailField('Email', validators=[DataRequired(), Email()]) email = EmailField('Email', validators=[DataRequired(), Email()])

def validate(self): def validate(self):
if Form.validate(self): if Form.validate(self):
client_id = add_client_id(self.email.data, self.name.data) client_id = add_client_id(self.email.data, self.name.data)
if client_id: if client_id:
send_id_email(self.email.data, self.name.data, client_id) send_id_email(self.email.data, self.name.data, client_id)
Expand All @@ -23,16 +24,17 @@ def validate(self):
else: else:
return False return False



class DocumentationForm(Form): class DocumentationForm(Form):
name = StringField('Name', validators=[DataRequired()]) name = StringField('Name', validators=[DataRequired()])
urlname = StringField('URL Name', validators=[DataRequired()]) urlname = StringField('URL Name', validators=[DataRequired()])
imageurl = StringField('Image URL', validators=[DataRequired()]) imageurl = StringField('Image URL', validators=[DataRequired()])
contents = TextAreaField('Contents', validators=[DataRequired()]) contents = TextAreaField('Contents', validators=[DataRequired()])


def validate(self): def validate(self):
if Form.validate(self): if Form.validate(self):
documentation = add_documentation(self.contents.data, documentation = add_documentation(self.contents.data,
self.name.data, self.urlname.data, self.imageurl.data) self.name.data, self.urlname.data, self.imageurl.data)
if documentation: if documentation:
return True return True
else: else:
Expand All @@ -41,15 +43,16 @@ def validate(self):
else: else:
return False return False



class MemberForm(Form): class MemberForm(Form):
name = StringField('Name', validators=[DataRequired()]) name = StringField('Name', validators=[DataRequired()])
imageurl = StringField('Image URL', validators=[DataRequired()]) imageurl = StringField('Image URL', validators=[DataRequired()])
about = TextAreaField('Contents', validators=[DataRequired()]) about = TextAreaField('Contents', validators=[DataRequired()])


def validate(self): def validate(self):
if Form.validate(self): if Form.validate(self):
member = add_member(self.about.data, member = add_member(self.about.data,
self.name.data, self.imageurl.data) self.name.data, self.imageurl.data)
if member: if member:
return True return True
else: else:
Expand Down
48 changes: 28 additions & 20 deletions api/meta.py

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions api/scripts/add_client.py
Expand Up @@ -10,6 +10,7 @@
# simplify collection name # simplify collection name
clients = db.clients clients = db.clients



def add_client_id(email, username, client_id=None): def add_client_id(email, username, client_id=None):
if email[-10:] != '@brown.edu': if email[-10:] != '@brown.edu':
print("Invalid student email") print("Invalid student email")
Expand All @@ -22,12 +23,12 @@ def add_client_id(email, username, client_id=None):
while clients.find_one({'client_id': client_id}): while clients.find_one({'client_id': client_id}):
client_id = str(uuid4()) client_id = str(uuid4())
new_client = { new_client = {
'client_id': client_id, 'client_id': client_id,
'username': username, 'username': username,
'client_email': email, 'client_email': email,
'joined': str(datetime.now()), 'joined': str(datetime.now()),
'valid': True 'valid': True
} }
clients.insert(new_client) clients.insert(new_client)
return client_id return client_id


Expand All @@ -38,7 +39,7 @@ def add_client_id(email, username, client_id=None):
print("\tusername - Required. A user who owns this client (typically a first and last name, like 'Josiah Carberry').") print("\tusername - Required. A user who owns this client (typically a first and last name, like 'Josiah Carberry').")
print("\tclient_id - Optional. Provide a string representation of a UUID4 client ID.") print("\tclient_id - Optional. Provide a string representation of a UUID4 client ID.")
exit() exit()

if len(argv) == 3: if len(argv) == 3:
client_id = add_client_id(argv[1], argv[2]) client_id = add_client_id(argv[1], argv[2])
if len(argv) == 4: if len(argv) == 4:
Expand Down
11 changes: 6 additions & 5 deletions api/scripts/add_documentation.py
Expand Up @@ -2,12 +2,13 @@


api_documentations = db.api_documentations api_documentations = db.api_documentations



def add_documentation(contents, name, urlname, imageurl): def add_documentation(contents, name, urlname, imageurl):
new_documentation = { new_documentation = {
'name': name, 'name': name,
'urlname': urlname, 'urlname': urlname,
'contents': contents, 'contents': contents,
'imageurl': imageurl 'imageurl': imageurl
} }
api_documentations.insert(new_documentation) api_documentations.insert(new_documentation)
return True return True
9 changes: 5 additions & 4 deletions api/scripts/add_member.py
Expand Up @@ -2,11 +2,12 @@


api_members = db.members api_members = db.members



def add_member(about, name, imageurl): def add_member(about, name, imageurl):
new_member = { new_member = {
'name': name, 'name': name,
'about': about, 'about': about,
'image_url': imageurl 'image_url': imageurl
} }
api_members.insert(new_member) api_members.insert(new_member)
return True return True
10 changes: 5 additions & 5 deletions api/scripts/disable_client.py
@@ -1,9 +1,9 @@
from sys import argv from sys import argv


from api import db, meta from api import meta


if __name__ == '__main__': if __name__ == '__main__':
if len(argv) != 2: if len(argv) != 2:
print("Usage: python -m api.scripts.disable_client <client_id>") print("Usage: python -m api.scripts.disable_client <client_id>")
else: else:
print(meta.invalidate_client(argv[1])) print(meta.invalidate_client(argv[1]))

0 comments on commit a1a8fca

Please sign in to comment.