Skip to content

Commit

Permalink
fix conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
joengelm committed Jan 31, 2016
2 parents 838734b + b250942 commit eac224d
Show file tree
Hide file tree
Showing 56 changed files with 14,195 additions and 38 deletions.
11 changes: 11 additions & 0 deletions README.md
Expand Up @@ -69,6 +69,17 @@ We use MongoDB to store various menus and schedules, as well as client informati
* _endpoint_: &lt;STRING&gt; **<-- endpoint of request**
- **DEPRECATED:** *client_name*: &lt;STRING&gt; **<-- replaced with _username_**

### db.api_documentations ###
- *urlname*: &lt;STRING&gt;
- *name*: &lt;STRING&gt;
- *contents*: &lt;STRING&gt;
- *imageurl*: &lt;IMAGE&gt;

### db.members ###
- *name*: &lt;STRING&gt;
- *image_url*: &lt;STRING&gt;
- *about*: &lt;STRING&gt;

### db.dining\_menus ###

- *eatery*: &lt;STRING&gt;,
Expand Down
36 changes: 34 additions & 2 deletions api/__init__.py
@@ -1,4 +1,4 @@
from flask import Flask, jsonify, request, current_app
from flask import Flask, jsonify, request, current_app, Response
from werkzeug.exceptions import default_exceptions
from werkzeug.exceptions import HTTPException
from functools import wraps
Expand Down Expand Up @@ -35,7 +35,6 @@ def decorated_function(*args, **kwargs):
return f(*args, **kwargs)
return decorated_function


# initialize the app and allow an instance configuration file
app = Flask(__name__, instance_relative_config=True)
try:
Expand All @@ -59,6 +58,39 @@ def decorated_function(*args, **kwargs):
else:
print("The database URI's environment variable was not found.")



# BASIC AUTH

def check_auth(username, password):
"""This function is called to check if a username /
password combination is valid.
"""
if 'DASHBOARD_PASS' in app.config:
correct_password = app.config['DASHBOARD_PASS']
elif 'DASHBOARD_PASS' in os.environ:
correct_password = os.environ['DASHBOARD_PASS']
else:
print("The dashboard password's environment variable was not found.")
return username == 'admin' and password == correct_password

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

def requires_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
auth = request.authorization
if not auth or not check_auth(auth.username, auth.password):
return authenticate()
return f(*args, **kwargs)
return decorated


import api.meta
import api.dining
import api.wifi
Expand Down
59 changes: 59 additions & 0 deletions api/forms.py
@@ -0,0 +1,59 @@
from flask_wtf import Form
from wtforms import StringField, TextAreaField
from wtforms.fields.html5 import EmailField
from wtforms.validators import DataRequired, Email
from api.scripts.add_client import add_client_id
from api.scripts.email_handler import send_id_email
from api.scripts.add_documentation import add_documentation
from api.scripts.add_member import add_member

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

def validate(self):
if Form.validate(self):
client_id = add_client_id(self.email.data, self.name.data)
if client_id:
send_id_email(self.email.data, self.name.data, client_id)
return True
else:
self.email.errors.append("Client ID could not be created. Is your email correct?")
return False
else:
return False

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

def validate(self):
if Form.validate(self):
documentation = add_documentation(self.contents.data,
self.name.data, self.urlname.data, self.imageurl.data)
if documentation:
return True
else:
self.name.errors.append("Client ID could not be created.")
return False
else:
return False

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

def validate(self):
if Form.validate(self):
member = add_member(self.about.data,
self.name.data, self.imageurl.data)
if member:
return True
else:
self.name.errors.append("Member could not be created.")
return False
else:
return False
90 changes: 59 additions & 31 deletions api/meta.py
@@ -1,56 +1,84 @@
from flask import render_template, url_for, request, redirect
from functools import wraps
from api import make_json_error
from api import app, db
from api.scripts.add_client import add_client_id
from api.scripts.email_handler import send_id_email
from flask import jsonify, render_template, url_for, request, redirect
from flask import send_from_directory
from api import app, db, requires_auth
from api.scripts.stats import get_total_requests
from datetime import datetime
from api.forms import SignupForm, DocumentationForm, MemberForm
from flask import Markup
import markdown

'''
DATABASE OBJECTS: View templates on the private, repository README.
'''

# simplify collection names
clients = db.clients
api_documentations = db['api_documentations']
members = db['members']

# Messages for success/failure during Client ID signup
SUCCESS_MSG = "Your Client ID has been emailed to you!"
FAILURE_MSG = ("Your request could not be processed. "
"Please email 'joseph_engelman@brown.edu' for "
"manual registration.")

@app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path, 'static'),
'favicon.ico')


@app.route('/')
def root():
signed_up = request.args.get('signedup', '')
num_requests = get_total_requests()
if signed_up == 'true':
return render_template('documentation.html',
message=SUCCESS_MSG,
num_requests=num_requests)
if signed_up == 'false':
return render_template('documentation.html',
message=FAILURE_MSG,
num_requests=num_requests)
else:
return render_template('documentation.html', num_requests=num_requests)
# num_requests = get_total_requests()
return render_template('home.html',
api_documentations=list(api_documentations.find()))

@app.route('/signup', methods=['GET', 'POST'])
def signup():
if request.method == 'GET':
return render_template('signup.html')
else:
firstname = request.form['firstname'].strip()
lastname = request.form['lastname'].strip()
email = request.form['email'].strip()
client_id = add_client_id(email, firstname + " " + lastname)
if client_id:
send_id_email(email, firstname, client_id)
return redirect(url_for('root', signedup='true'))
else:
return redirect(url_for('root', signedup='false'))

form = SignupForm()
if form.validate_on_submit():
return redirect(url_for('root', signedup='true'))
return render_template('signup.html', form=form, active="signup",
api_documentations=api_documentations.find())

@app.route('/docs', methods=['GET'])
def docs():
return redirect('/docs/getting-started') #TODO: Fix this part to use url_for

@app.route('/docs/<docName>', methods=['GET'])
def docs_for(docName="getting-started"):
api_documentation=api_documentations.find_one({'urlname': docName})
name=api_documentation['name']
contents=api_documentation['contents']
contents=Markup(markdown.markdown(contents))
return render_template('documentation_template.html',
api_documentations=list(api_documentations.find()),
name=name, contents=contents, active="docs")

@app.route('/about-us', methods=['GET', 'POST'])
def about_us():
return render_template('about-us.html',
api_documentations=list(api_documentations.find()),
active="about", members=members.find())

@app.route('/admin/add-documentation', methods=['GET', 'POST'])
@requires_auth
def add_documentation():
form = DocumentationForm()
if form.validate_on_submit():
return redirect(url_for('root'))
return render_template('add_documentation.html', form=form,
api_documentations=list(api_documentations.find()))

@app.route('/admin/add-member', methods=['GET', 'POST'])
@requires_auth
def add_member():
form = MemberForm()
if form.validate_on_submit():
return redirect(url_for('root'))
return render_template('add_member.html', form=form,
api_documentations=list(api_documentations.find()))

# Static responses

Expand Down
2 changes: 1 addition & 1 deletion api/scripts/add_client.py
Expand Up @@ -47,4 +47,4 @@ def add_client_id(email, username, client_id=None):
if not client_id:
print("Email is not a Brown address. Unable to add client to database.")
else:
print("Client ID: ", client_id)
print("Client ID: ", client_id)
13 changes: 13 additions & 0 deletions api/scripts/add_documentation.py
@@ -0,0 +1,13 @@
from api import db

api_documentations = db.api_documentations

def add_documentation(contents, name, urlname, imageurl):
new_documentation = {
'name': name,
'urlname': urlname,
'contents': contents,
'imageurl': imageurl
}
api_documentations.insert(new_documentation)
return True
12 changes: 12 additions & 0 deletions api/scripts/add_member.py
@@ -0,0 +1,12 @@
from api import db

api_members = db.members

def add_member(about, name, imageurl):
new_member = {
'name': name,
'about': about,
'image_url': imageurl
}
api_members.insert(new_member)
return True
6 changes: 3 additions & 3 deletions api/scripts/email_handler.py
Expand Up @@ -7,7 +7,7 @@
URGENT_RECEPIENT = "7172159174@vtext.com"
ALERT_RECEPIENT = "joseph_engelman@brown.edu"

def send_id_email(address, firstname, client_id):
def send_id_email(address, name, client_id):
# me == my email address
# you == recipient's email address
me = os.environ['GMAIL_USER']
Expand All @@ -19,7 +19,7 @@ def send_id_email(address, firstname, client_id):
msg['To'] = address

# Create the body of the message (a plain-text and an HTML version).
text = "Hi, " + firstname + "! Welcome to the Brown APIs developer community.\nYour Client ID is: " + client_id + ". Be sure to include it in every request!) You can use this Client ID for multiple projects. There is currently a maximum of one Client ID per student, but exceptions can be made on a case-by-case basis.\n\nBrown APIs are currently in beta. This means functionality may be added, removed, or modified at any time (however, this is very rare). To keep up-to-date on any changes, be sure to join the developer community on Facebook: https://www.facebook.com/groups/brown.apis/\n\nHappy developing!\nThe Brown APIs Team\n"
text = "Hi, " + name + "! Welcome to the Brown APIs developer community.\nYour Client ID is: " + client_id + ". Be sure to include it in every request!) You can use this Client ID for multiple projects. There is currently a maximum of one Client ID per student, but exceptions can be made on a case-by-case basis.\n\nBrown APIs are currently in beta. This means functionality may be added, removed, or modified at any time (however, this is very rare). To keep up-to-date on any changes, be sure to join the developer community on Facebook: https://www.facebook.com/groups/brown.apis/\n\nHappy developing!\nThe Brown APIs Team\n"
html = """\
<html>
<head>
Expand All @@ -34,7 +34,7 @@ def send_id_email(address, firstname, client_id):
</style>
</head>
<body>
<h2 class="center">Hi, """ + firstname + """! Welcome to the Brown APIs developer community.</h2>
<h2 class="center">Hi, """ + name + """! Welcome to the Brown APIs developer community.</h2>
<p>Your Client ID is: <em>""" + client_id + """</em>.</p>
<p>Be sure to include your Client ID with every request you make! You can use this Client ID for multiple projects. Currently, there is a maximum of one Client ID per student, but exceptions can be made on a case-by-case basis.</p>
<p>Brown APIs are currently in beta. This means functionality may be added, removed, or modified at any time (however, this is very rare). To keep up-to-date on any changes, be sure to join our <a href="https://www.facebook.com/groups/brown.apis/">community of developers</a> on Facebook.</p>
Expand Down
3 changes: 3 additions & 0 deletions api/static/about.css
@@ -0,0 +1,3 @@
.img-member {
margin: 20px;
}

0 comments on commit eac224d

Please sign in to comment.