Commit 73c6494d authored by danmcquillan's avatar danmcquillan

adding lab-17

parent c1e9e5bb
import pymysql
import datetime
import hashlib
class DBHelper:
def __init__(self):
self.db = pymysql.connect(host='localhost',
user='mytwits_user',
passwd='mytwits_password',
db='mytwits')
def get_user(self, user_id):
query = "select * from users where user_id=%s"
with self.db.cursor() as cursor:
cursor.execute(query,user_id)
return cursor.fetchone()
def get_all_twits(self):
query = "select u.username, t.twit_id, t.twit, t.created_at from twits t, users u where t.user_id=u.user_id order by t.created_at desc;"
with self.db.cursor() as cursor:
cursor.execute(query)
return cursor.fetchall() # The method fetches all (or all remaining) rows of a query result set and returns a list of tuples
def get_twit(self,twit_id):
query = "select twit from twits where twit_id=%s"
with self.db.cursor() as cursor:
cursor.execute(query, twit_id)
return cursor.fetchone()
# more detals about cursor.fetchone at
# https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-fetchone.html
def get_user_twits(self,username):
query = "select u.username, t.twit, t.created_at from twits t,\
users u where t.user_id=u.user_id and u.username=%s order by t.created_at desc;"
with self.db.cursor() as cursor:
cursor.execute(query,(username))
return cursor.fetchall() # The method fetches all (or all remaining) rows of a query result set and returns a list of tuples
#
def add_twit(self,twit,user_id):
query = "insert into twits (twit,user_id) values \
(%s,%s);"
with self.db.cursor() as cursor:
cursor.execute(query, (twit,user_id))
return self.db.commit()
def update_twit(self,twit,twit_id):
query = "update twits set twit=%s where twit_id=%s"
with self.db.cursor() as cursor:
cursor.execute(query,(twit,twit_id))
return self.db.commit()
def delete_twit(self,twit_id):
query = "delete from twits where twit_id=%s"
with self.db.cursor() as cursor:
cursor.execute(query, twit_id)
return self.db.commit()
def check_password(self,username,password):
query = "select user_id, salt, hashed from users where username = %s;"
with self.db.cursor() as cursor:
cursor.execute(query,(username))
user = cursor.fetchone()
if user:
user_id, salt, hashed = user
if hashlib.sha512((salt + password).encode('utf-8')).hexdigest() == hashed:
return user_id
return None
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms import HiddenField
from wtforms import PasswordField
from wtforms import SubmitField
from wtforms import validators
class addTwitForm(FlaskForm):
twit = StringField('twit', validators = [validators.DataRequired()])
submit = SubmitField('submit', [validators.DataRequired()])
class editTwitForm(FlaskForm):
twit = StringField('twit', validators = [validators.DataRequired()])
twit_id = HiddenField('twit_id')
submit = SubmitField('submit', [validators.DataRequired()])
class loginForm(FlaskForm):
username = StringField('username', validators = [validators.DataRequired()])
password = PasswordField('password', validators =[validators.DataRequired()])
password2 = PasswordField('password2', validators=[validators.DataRequired(),
validators.EqualTo('password', message='Passwords must match')])
submit = SubmitField('submit', [validators.DataRequired()])
from flask import Flask, request
from flask import render_template
from flask import redirect, url_for
from flask import session, flash, abort
from flask import jsonify
from vs_url_for import vs_url_for
from forms import addTwitForm, editTwitForm, loginForm
from dbhelper import DBHelper
from flask_login import LoginManager, login_required
from flask_login import login_user, logout_user
from user import User
login_manager = LoginManager()
app = Flask(__name__)
db = DBHelper()
login_manager.init_app(app)
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
@login_manager.user_loader
def load_user(user_id):
result = db.get_user(user_id)
if result:
return User(user_id)
@app.route('/')
def index():
twits = db.get_all_twits()
return render_template("mytwits_mysql.html", twits=twits)
@app.route('/add_twit', methods = ['GET', 'POST'])
@login_required
def add_twit():
form = addTwitForm()
if form.validate_on_submit():
twit = form.twit.data
db.add_twit(twit,session['user_id'])
return redirect(vs_url_for('index'))
return render_template('add_twit_mysql.html',form=form)
@app.route('/edit_twit', methods = ['GET', 'POST'])
@login_required
def edit_twit():
form = editTwitForm()
if request.args.get('id'):
twit_id = request.args.get('id')
twit = db.get_twit(twit_id)
form.twit.data = twit[0]
form.twit_id.data = twit_id
return render_template('edit_twit_mysql.html',form=form,twit=twit)
if form.validate_on_submit():
twit = form.twit.data
twit_id = form.twit_id.data
db.update_twit(twit,twit_id)
return redirect(vs_url_for('index'))
return render_template('edit_twit_mysql.html',form=form)
@app.route('/delete_twit', methods = ['GET', 'POST'])
@login_required
def delete_twit():
if request.args.get('id'):
twit_id = request.args.get('id')
twit = db.delete_twit(twit_id)
return redirect(vs_url_for('index'))
@app.route('/login', methods = ['GET', 'POST'])
def login():
form = loginForm()
if form.validate_on_submit():
password = form.password.data
username = form.username.data
user_id = db.check_password(username,password)
if user_id:
user = User(user_id)
login_user(user)
flash('login successful!')
return redirect(vs_url_for('index'))
else:
flash('login unsuccessful!')
return render_template('login.html',form=form)
@app.route('/api')
@app.route('/api/<username>')
def api(username=None):
if username:
twits = db.get_user_twits(username)
return jsonify({'twits':twits})
else:
twits = db.get_all_twits()
return jsonify({'twits':twits})
@app.route('/logout')
def logout():
# remove the username from the session if it's there
logout_user()
return redirect(vs_url_for('index'))
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0',port=8000)
{% extends "base.html" %}
{% block body %}
<div class="jumbotron">
<div >
<form class="form-horizontal" method="post" action="/add_twit">
{{ form.csrf_token }}
<div class='form-group'>
<div class='col-md-6'>
{% if form.twit.errors %}
<ul class='errors'>
{% for error in form.twit.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{ form.twit(class='form-control',placeholder='twit') }}
</div>
</div>
<div class='form-group'>
<div class='col-md-6'>
{{ form.submit(class='btn btn-primary btn-block') }}
</div>
</div>
</form>
</div>
</div>
{% endblock %}
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css"
integrity="sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy"
crossorigin="anonymous">
</head>
<body>
<div class="container">
<!--- flash messages -->
{% for category, message in get_flashed_messages(with_categories=true) %}
<div class="alert alert-dismissable alert-warning alert-{{ category }}">
<button type="button" class="close" data-dismiss="alert">&times;</button>
{{ message }}
</div>
{% endfor %}
<!--- the body will come from a template that inherits from this one -->
{% block body %}{% endblock %}
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/js/bootstrap.min.js" integrity="sha384-a5N7Y/aK3qNeh15eJKGWxsqtnX/wWdSZSKp+81YjTmS15nvnvxKHuzaWwXHDli+4" crossorigin="anonymous"></script>
</body>
</html>
{% extends "base.html" %}
{% block body %}
<div class="jumbotron">
<div >
<form class="form-horizontal" method="post" action="/edit_twit">
{{ form.csrf_token }}
<div class='form-group'>
<div class='col-md-6'>
{% if form.twit.errors %}
<ul class='errors'>
{% for error in form.twit.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{ form.twit(class='form-control') }}
</div>
</div>
<div>
{{ form.twit_id }}
</div>
<div class='form-group'>
<div class='col-md-6'>
{{ form.submit(class='btn btn-primary btn-block') }}
</div>
</div>
</form>
</div>
</div>
{% endblock %}
{% extends "base.html" %}
{% block body %}
<div class="jumbotron">
<form class='form-horizontal' method="post">
{{ form.csrf_token }}
<div class='form-group'>
<div class='col-md-6'>
{% if form.username.errors %}
<ul class='errors'>
{% for error in form.username.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{ form.username(class='form-control',placeholder='username') }}
</div>
</div>
<div class='form-group'>
<div class='col-md-6'>
{% if form.password.errors %}
<ul class='errors'>
{% for error in form.password.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{
form.password(class='form-control',placeholder='password') }}
</div>
</div>
<div class='form-group'>
<div class='col-md-6'>
{% if form.password2.errors %}
<ul class='errors'>
{% for error in form.password2.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{ form.password2(class='form-control',placeholder='confirm password') }}
</div>
</div>
<div class='form-group'>
<div class='col-md-6'>
{{ form.submit(class='btn btn-primary btn-block') }}
</div>
</div>
</form>
</div >
{% endblock %}
{% extends "base.html" %}
{% block body %}
<div class="jumbotron">
{% for twit in twits %}
<div class="row">
<div class="col-md-4">{{ twit[0] }}</div>
<div class="col-md-4">{{ twit[2] }}</div>
<div class="col-md-4"><a href='/edit_twit?id={{ twit[1] }}'> edit </a><a
href='/delete_twit?id={{ twit[1] }}'> delete </a></div>
</div>
{% endfor %}
</div>
{% endblock %}
class User:
def __init__(self, user_id):
self.user_id = user_id
@property
def username(self):
return self.username
@property
def is_authenticated(self):
return True
@property
def is_active(self):
return True
@property
def is_anonymous(self):
return False
def get_id(self):
return self.user_id
def __repr__(self):
return 'user_id {}'.format(self.user_id)
from flask import url_for
#URL_PREFIX = '/usr/253'
URL_PREFIX = ''
def vs_url_for(view):
url = url_for(view)
url = URL_PREFIX + url
return url
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms import HiddenField
from wtforms import PasswordField
from wtforms import SubmitField
from wtforms import validators
class addTwitForm(FlaskForm):
twit = StringField('twit', validators = [validators.DataRequired()])
submit = SubmitField('submit', [validators.DataRequired()])
class editTwitForm(FlaskForm):
twit = StringField('twit', validators = [validators.DataRequired()])
twit_id = HiddenField('twit_id')
submit = SubmitField('submit', [validators.DataRequired()])
class loginForm(FlaskForm):
username = StringField('username', validators = [validators.DataRequired()])
password = PasswordField('password', validators =[validators.DataRequired()])
password2 = PasswordField('password2', validators=[validators.DataRequired(),
validators.EqualTo('password', message='Passwords must match')])
submit = SubmitField('submit', [validators.DataRequired()])
from flask import Flask, request
from flask import render_template
from flask import redirect, url_for
from flask import session, flash, abort
from flask import jsonify
from vs_url_for import vs_url_for
from forms import addTwitForm, editTwitForm, loginForm
from dbhelper import DBHelper
from flask_login import LoginManager, login_required
from flask_login import login_user, logout_user
from user import User
from flask_restful import Resource, Api
from flask_restful import fields, marshal_with
from flask_restful import reqparse
login_manager = LoginManager()
app = Flask(__name__)
db = DBHelper()
login_manager.init_app(app)
api = Api(app)
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
#----resource fields to filter the output for flask-restful
resource_fields = {
'twit_id': fields.Integer,
'twit': fields.String,
'user_id': fields.Integer,
'created_at': fields.DateTime(dt_format='rfc822')
}
#----parse and verify the api inputs
parser = reqparse.RequestParser()
parser.add_argument('twit', type=str, help='the text of the twit; must be a string')
parser.add_argument('twit_id', type=int, help='the id of the twit; must be an integer')
parser.add_argument('user_id', type=int, help='the id of the twit; must be an integer')
#----instantiating the resource; the main part of the flask-restful api
class TwitsApi(Resource):
@marshal_with(resource_fields)
def get(self):
return db.get_all_twits()
@marshal_with(resource_fields)
def post(self):
args = parser.parse_args()
twit = args['twit']
user_id = args['user_id']
db.add_twit(twit,user_id)
return db.get_all_twits()
class TwitsIdApi(Resource):
@marshal_with(resource_fields)
def get(self, twit_id):
if db.get_twit(twit_id):
return db.get_twit(twit_id)
abort(404)
@marshal_with(resource_fields)
def put(self,twit_id):
args = parser.parse_args()
twit = args['twit']
db.update_twit(twit,twit_id)
return db.get_all_twits()
@marshal_with(resource_fields)
def delete(self, twit_id):
db.delete_twit(twit_id)
return db.get_all_twits()
#----assigning a route for the api
api.add_resource(TwitsApi,'/api')
api.add_resource(TwitsIdApi,'/api/<int:twit_id>')
#---- the callback function for flask-login
@login_manager.user_loader
def load_user(user_id):
result = db.get_user(user_id)
if result:
return User(user_id)
@app.route('/')
def index():
twits = db.get_all_twits()
return render_template("mytwits_mysql.html", twits=twits)
@app.route('/add_twit', methods = ['GET', 'POST'])
@login_required
def add_twit():
form = addTwitForm()
if form.validate_on_submit():
twit = form.twit.data
db.add_twit(twit,session['user_id'])
return redirect(vs_url_for('index'))
return render_template('add_twit_mysql.html',form=form)
@app.route('/edit_twit', methods = ['GET', 'POST'])
@login_required
def edit_twit():
form = editTwitForm()
if request.args.get('id'):
twit_id = request.args.get('id')
twit = db.get_twit(twit_id)
form.twit.data = twit['twit']
form.twit_id.data = twit_id
return render_template('edit_twit_mysql.html',form=form,twit=twit)
if form.validate_on_submit():
twit = form.twit.data
twit_id = form.twit_id.data
db.update_twit(twit,twit_id)
return redirect(vs_url_for('index'))
return render_template('edit_twit_mysql.html',form=form)
@app.route('/delete_twit', methods = ['GET', 'POST'])
@login_required
def delete_twit():
if request.args.get('id'):
twit_id = request.args.get('id')
twit = db.delete_twit(twit_id)
return redirect(vs_url_for('index'))
@app.route('/login', methods = ['GET', 'POST'])
def login():
form = loginForm()
if form.validate_on_submit():
password = form.password.data
username = form.username.data
user_id = db.check_password(username,password)
if user_id:
user = User(user_id)
login_user(user)
flash('login successful!')
return redirect(vs_url_for('index'))
else:
flash('login unsuccessful!')
return render_template('login.html',form=form)
@app.route('/logout')
def logout():
# remove the username from the session if it's there
logout_user()
return redirect(vs_url_for('index'))
if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0',port=8000)
{% extends "base.html" %}
{% block body %}
<div class="jumbotron">
<div >
<form class="form-horizontal" method="post" action="/add_twit">
{{ form.csrf_token }}
<div class='form-group'>
<div class='col-md-6'>
{% if form.twit.errors %}
<ul class='errors'>
{% for error in form.twit.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
{{ form.twit(class='form-control',placeholder='twit') }}
</div>
</div>
<div class='form-group'>
<div class='col-md-6'>