-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2216e87
commit c5834f3
Showing
7 changed files
with
335 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import os | ||
from flask import Flask, render_template, redirect, session, g, flash | ||
|
||
from forms import LoginForm, UserAddForm, CocktailForm | ||
from models import db, connect_db, User, Cocktails | ||
|
||
CURR_USER_KEY = 'curr_user' | ||
|
||
app = Flask(__name__) | ||
|
||
app.config['SQLALCHEMY_DATABASE_URI'] = (os.environ.get('DATABASE_URL', 'postgresql://drinks')) | ||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False | ||
app.config['SQLALCHEMY_ECHO'] = False | ||
app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', "it's a secret") | ||
|
||
connect_db(app) | ||
|
||
# User join/login/logout | ||
|
||
@app.before_request | ||
def add_user_to_g(): | ||
"""If we're logged in, add curr user to Flask global.""" | ||
|
||
if CURR_USER_KEY in session: | ||
g.user = User.query.get(session[CURR_USER_KEY]) | ||
|
||
else: | ||
g.user = None | ||
|
||
|
||
def do_login(user): | ||
"""Log in user.""" | ||
|
||
session[CURR_USER_KEY] = user.id | ||
|
||
|
||
def do_logout(): | ||
"""Logout user.""" | ||
|
||
if CURR_USER_KEY in session: | ||
del session[CURR_USER_KEY] | ||
|
||
|
||
@app.route('/signup', methods=["GET", "POST"]) | ||
def signup(): | ||
"""Handle user signup. | ||
Create new user and add to DB. Redirect to home page. | ||
If form not valid, present form. | ||
If the there already is a user with that username: flash message | ||
and re-present form. | ||
""" | ||
if CURR_USER_KEY in session: | ||
del session[CURR_USER_KEY] | ||
form = UserAddForm() | ||
|
||
if form.validate_on_submit(): | ||
try: | ||
user = User.signup( | ||
username=form.username.data, | ||
password=form.password.data, | ||
email=form.email.data | ||
) | ||
db.session.commit() | ||
|
||
except IntegrityError as e: | ||
flash("Username already taken", 'danger') | ||
return render_template('users/signup.html', form=form) | ||
|
||
do_login(user) | ||
|
||
return redirect("/") | ||
|
||
else: | ||
return render_template('users/signup.html', form=form) | ||
|
||
|
||
@app.route('/login', methods=["GET", "POST"]) | ||
def login(): | ||
"""Handle user login.""" | ||
|
||
form = LoginForm() | ||
|
||
if form.validate_on_submit(): | ||
user = User.authenticate(form.username.data, | ||
form.password.data) | ||
|
||
if user: | ||
do_login(user) | ||
flash(f"Hello, {user.username}!", "success") | ||
return redirect("/") | ||
|
||
flash("Invalid credentials.", 'danger') | ||
|
||
return render_template('users/login.html', form=form) | ||
|
||
|
||
@app.route('/logout') | ||
def logout(): | ||
"""Handle logout of user.""" | ||
|
||
do_logout() | ||
|
||
flash("You have successfully logged out.", 'success') | ||
return redirect("/login") | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from flask_wtf import FlaskForm | ||
from wtforms import StringField, PasswordField, TextAreaField | ||
from wtforms.validators import DataRequired, Email, Length | ||
|
||
class UserAddForm(FlaskForm): | ||
'''Form for adding users''' | ||
|
||
username = StringField('Username', validators=[DataRequired()]) | ||
email = StringField('Email', validators=[DataRequired(), Email()]) | ||
password = PasswordField('Password', validators=[Length(min=8)]) | ||
|
||
class LoginForm(FlaskForm): | ||
'''Form for logging in user''' | ||
|
||
username = StringField('Username', validators=[DataRequired()]) | ||
password = PasswordField('Password', validators=[Length(min=8)]) | ||
|
||
class CocktailForm(FlaskForm): | ||
'''Form for choosing cocktail to make''' | ||
|
||
cocktail = StringField('Cocktail') | ||
ingredients = StringField('Ingredient') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from flask_bcrypt import Bcrypt | ||
from flask_sqlalchemy import SQLAlchemy | ||
|
||
bcrypt = Bcrypt() | ||
db = SQLAlchemy() | ||
|
||
class Cocktails(db.Model): | ||
'''Cocktails''' | ||
|
||
__tablename__ = 'cocktails' | ||
|
||
name = db.Column(db.Text, ) | ||
image = db.Column(db.Text, ) | ||
instructions = db.Column(db.Text, ) | ||
ingredients = db.Column(db.Text, ) | ||
measurements = db.Column(db.Text, ) | ||
|
||
|
||
'''' USER CLASS''' | ||
|
||
|
||
class User(db.Model): | ||
"""User in the system.""" | ||
|
||
__tablename__ = 'users' | ||
|
||
id = db.Column( | ||
db.Integer, | ||
primary_key=True, | ||
) | ||
|
||
email = db.Column( | ||
db.Text, | ||
nullable=False, | ||
unique=True, | ||
) | ||
|
||
username = db.Column( | ||
db.Text, | ||
nullable=False, | ||
unique=True, | ||
) | ||
|
||
password = db.Column( | ||
db.Text, | ||
nullable=False, | ||
) | ||
|
||
|
||
def __repr__(self): | ||
return f"<User #{self.id}: {self.username}, {self.email}>" | ||
|
||
|
||
@classmethod | ||
def signup(cls, username, email, password): | ||
"""Sign up user. | ||
Hashes password and adds user to system. | ||
""" | ||
|
||
hashed_pwd = bcrypt.generate_password_hash(password).decode('UTF-8') | ||
|
||
user = User( | ||
username=username, | ||
email=email, | ||
password=hashed_pwd, | ||
) | ||
|
||
db.session.add(user) | ||
return user | ||
|
||
@classmethod | ||
def authenticate(cls, username, password): | ||
"""Find user with `username` and `password`. | ||
This is a class method (call it on the class, not an individual user.) | ||
It searches for a user whose password hash matches this password | ||
and, if it finds such a user, returns that user object. | ||
If can't find matching user (or if password is wrong), returns False. | ||
""" | ||
|
||
user = cls.query.filter_by(username=username).first() | ||
|
||
if user: | ||
is_auth = bcrypt.check_password_hash(user.password, password) | ||
if is_auth: | ||
return user | ||
|
||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
Schema for Cocktail App | ||
|
||
Table 1 - Users | ||
Table 1 - User | ||
username | ||
password | ||
|
||
Table 2 - Cocktails | ||
name | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
|
||
<head> | ||
<meta charset="UTF-8"> | ||
<title>Cocktail App</title> | ||
|
||
<link rel="stylesheet" | ||
href="https://unpkg.com/bootstrap/dist/css/bootstrap.css"> | ||
<script src="https://unpkg.com/jquery"></script> | ||
<script src="https://unpkg.com/popper"></script> | ||
<script src="https://unpkg.com/bootstrap"></script> | ||
|
||
<link rel="stylesheet" | ||
href="https://use.fontawesome.com/releases/v5.3.1/css/all.css"> | ||
<link rel="stylesheet" href="/static/stylesheets/style.css"> | ||
<link rel="shortcut icon" href="/static/favicon.ico"> | ||
</head> | ||
|
||
<body class="{% block body_class %}{% endblock %}"> | ||
<nav class="navbar navbar-expand"> | ||
<div class="container-fluid"> | ||
<div class="navbar-header"> | ||
<a href="/" class="navbar-brand"> | ||
<span>Cocktail</span> | ||
</a> | ||
</div> | ||
<ul class="nav navbar-nav navbar-right"> | ||
{% if request.endpoint != None %} | ||
<!-- <li> | ||
<form class="navbar-form navbar-right" action="/users"> | ||
<input name="q" class="form-control" placeholder="Search Warbler" id="search"> | ||
<button class="btn btn-default"> | ||
<span class="fa fa-search"></span> | ||
</button> | ||
</form> | ||
</li> --> | ||
{% endif %} | ||
{% if not g.user %} | ||
<li><a href="/signup">Sign up</a></li> | ||
<li><a href="/login">Log in</a></li> | ||
{% else %} | ||
<li> | ||
<a href="/users/{{ g.user.id }}"> | ||
</a> | ||
</li> | ||
<li><a href="/logout">Log out</a></li> | ||
{% endif %} | ||
</ul> | ||
</div> | ||
</nav> | ||
<!-- <div class="container"> | ||
{% for category, message in get_flashed_messages(with_categories=True) %} | ||
<div class="alert alert-{{ category }}">{{ message }}</div> | ||
{% endfor %} | ||
{% block content %} | ||
{% endblock %} | ||
</div> --> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{% extends 'base.html' %} | ||
|
||
{% block body_class %}onboarding{% endblock %} | ||
|
||
{% block content %} | ||
|
||
<div class="row justify-content-md-center"> | ||
<div class="col-md-7 col-lg-5"> | ||
<h2 class="join-message">Welcome back.</h2> | ||
|
||
<form method="POST" id="user_form"> | ||
{{ form.hidden_tag() }} | ||
|
||
{% for field in form if field.widget.input_type != 'hidden' %} | ||
{% for error in field.errors %} | ||
<span class="text-danger">{{ error }}</span> | ||
{% endfor %} | ||
{{ field(placeholder=field.label.text, class="form-control") }} | ||
{% endfor %} | ||
|
||
<button class="btn btn-primary btn-block btn-lg">Log in</button> | ||
</form> | ||
</div> | ||
</div> | ||
|
||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
{% extends 'base.html' %} | ||
|
||
{% block body_class %}onboarding{% endblock %} | ||
|
||
{% block content %} | ||
|
||
<div class="row justify-content-md-center"> | ||
<div class="col-md-7 col-lg-5"> | ||
<h2 class="join-message">Join Warbler today.</h2> | ||
<form method="POST" id="user_form"> | ||
{{ form.hidden_tag() }} | ||
|
||
{% for field in form if field.widget.input_type != 'hidden' %} | ||
{% for error in field.errors %} | ||
<span class="text-danger">{{ error }}</span> | ||
{% endfor %} | ||
{{ field(placeholder=field.label.text, class="form-control") }} | ||
{% endfor %} | ||
|
||
<button class="btn btn-primary btn-lg btn-block">Sign me up!</button> | ||
</form> | ||
</div> | ||
</div> | ||
|
||
{% endblock %} |