Permalink
Browse files

caught up on commits

  • Loading branch information...
roberto cortes
roberto cortes committed Feb 13, 2020
1 parent e6f87fe commit 5d454535b5666502684c1ca3fc2e4d9257c806fc
Showing with 260 additions and 6 deletions.
  1. +30 −2 app.py
  2. BIN dogs.sqlite
  3. +29 −2 models.py
  4. +5 −0 requirements.txt
  5. +31 −2 resources/dogs.py
  6. +165 −0 resources/users.py
32 app.py
@@ -11,9 +11,13 @@
from flask_cors import CORS


# login manager is the main tool for cooardinating session/login stuff in our app
from flask_login import LoginManager

from resources.dogs import dogs # import blueprint from ./resources/dogs

from resources.users import users

# in python you import a file and you get everything in the "global scope"
# of that file
# so this statement imports all variables and methods from that file as
@@ -29,7 +33,31 @@
# instantiating the Flask class
app = Flask(__name__)

# according to this - https://flask-login.readthedocs.io/en/latest/#configuring-your-application
# you need to import and config login manager

# 1. we need to setup a secret key
app.secret_key = 'AlsakdlkaskdlaskVery:sld. asklkSecrets;lda;lsaWoah'

# 2. instantiate to get a login_manager
login_manager = LoginManager()

# 3. actually connect app with lom

login_manager.init_app(app)


# in reg and login we did login_user(user that was found or created)
# that puts the ID of the user in session
# to use the user object whose is that is, you must define a cb
# for user_loader (part of login manger) tou use
# https://flask-login.readthedocs.io/en/latest/#how-it-works
@login_manager.user_loader
def load_user(user_id):
try:
return models.User.get(models.User.id == user_id)
except models.DoesNotExist:
return None
# CORS = Cross Origin Resource Sharing
# a web domain is an "origin"
# This app is localhost:8000, that's an origin
@@ -44,7 +72,7 @@
# third arg -- lets us accept requests with cookies attached, this allows us
# to use sessions for authentication
CORS(dogs, origins=['http://localhost:3000'], supports_credentials=True)

CORS(users, origins=['http://localhost:3000'], supports_credentials=True)

# we are using blueprints tio make "controllers"
# "use this blueprint (component/piece/section of the app) to handle dogs stuff"
@@ -53,7 +81,7 @@
# a different url prefix, and let your old API remain intact so that you don't
# break a bunch of apps already built on top of your old API with the old URLS
app.register_blueprint(dogs, url_prefix='/api/v1/dogs')

app.register_blueprint(users, url_prefix='/api/v1/users')

# we don't want to hog up the SQL connection pool
# so we should connect to the DB before every request
BIN +16 KB (300%) dogs.sqlite
Binary file not shown.
@@ -18,6 +18,25 @@
DATABASE = SqliteDatabase('dogs.sqlite')
# analogous to MONGO_DB_URL = 'mongodb://localhost/dogs', {...}

# we will use this module to setup user model, sessions, logins, auth
# require auth for certain things
# https://flask-login.readthedocs.io/en/latest/
from flask_login import UserMixin

# to behave correctly in flask-login's session/login/etc functionality
# the User class must have some methods and properties that model from peewee
# it doesn't have
# we could write these ourselves, and/or we could also have our User class
# inheirt from UserMixin (in addition to peewees model class), which
# will provide/implement them for us

class User(UserMixin, Model):
username = CharField(unique=True)
email = CharField(unique=True) # in sql unique is a constraint
password = CharField()

class Meta:
database = DATABASE


# defining our Dog model
@@ -27,7 +46,15 @@
# http://docs.peewee-orm.com/en/latest/peewee/models.html#fields
class Dog(Model):
name = CharField() # string
owner = CharField() # string for now, later we will implement a relation

# we will need a foreign key

owner = ForeignKeyField(User, backref='dogs') # string for now, later we will implement a relation
# if we had a dog model in a variable called some dog, the backref
# 'some_dog.owner' to get the owner
# and if we had the user model in a var called some_user, the backref
# will allow us to go some_user.dogs to get a list of dog instances

breed = CharField()
# this is how you specify default values
created_at = DateTimeField(default=datetime.datetime.now)
@@ -49,7 +76,7 @@ def initialize(): # NOTE we are making this name up
# create_tables first arg is list of tables to create
# second argument -- safe=True -- this means create tables only if it
# doesn't already exist
DATABASE.create_tables([Dog], safe=True)
DATABASE.create_tables([User, Dog], safe=True)
print("Connected to DB and created tables if they weren't already there")

# with SQL, don't leave DB connection open, we don't want to hog up space
@@ -1,10 +1,15 @@
bcrypt==3.1.7
cffi==1.14.0
Click==7.0
Flask==1.1.1
Flask-Bcrypt==0.7.1
Flask-Cors==3.0.8
Flask-Login==0.5.0
itsdangerous==1.1.0
Jinja2==2.11.1
MarkupSafe==1.1.1
peewee==3.13.1
psycopg2==2.8.4
pycparser==2.19
six==1.14.0
Werkzeug==1.0.0
@@ -8,7 +8,7 @@

# this is some useful extra tools that come with peewee
from playhouse.shortcuts import model_to_dict

from flask_login import current_user
# blueprint is a way to modularize apps, and group related functionality
# https://flask.palletsprojects.com/en/1.1.x/tutorial/views/
# we are using blueprints to make something analogous to a controller
@@ -58,7 +58,10 @@ def create_dog():
print(payload) # you should now see request data on terminal

# use our peewee model to add something to database
dog = models.Dog.create(name=payload['name'], owner=payload['owner'], breed=payload['breed'])
dog = models.Dog.create(
name=payload['name'],
owner=current_user.id, # this only works with .id
breed=payload['breed'])

print(dog) # just prints the ID -- check in sqlite3 on the command line
# run sqlite3 dogs.sqlite to open a CLI that lets you enter SQL queries
@@ -76,6 +79,8 @@ def create_dog():

dog_dict=model_to_dict(dog)

dog_dict['owner'].pop('password')

# notice you can add 201 to the return and you will send a proper HTTP status code
return jsonify(
data=dog_dict,
@@ -121,3 +126,27 @@ def update_dog(id):
status=200
), 200


@dogs.route('/<owner_id>', methods=['POST'])
def create_dog_with_owner(owner_id):
payload = request.get_json()
print(payload)
print(owner_id)

dog = models.Dog.create(
name=payload['name'],
breed=payload['breed'],
owner=owner_id
)

dog_dict = model_to_dict(dog)
print(dog_dict)

# remove password from the owner

dog_dict['owner'].pop('password')
return jsonify(
data=dog_dict,
message='Successfully created a dog with a owner {}'.format(dog_dict),
status=201
), 201
@@ -0,0 +1,165 @@
# like a user controller or auth controller in unit 2
import models

from flask import Blueprint, request, jsonify
from flask_bcrypt import generate_password_hash, check_password_hash
from flask_login import login_user, current_user, logout_user

# login_user is a function that will do the session stuff
# we manually had to do in express

from playhouse.shortcuts import model_to_dict
# make this a blueprint
users = Blueprint('users', 'users')

@users.route('/', methods=['GET'])
def test_user_resources():
return 'we have user resource'

@users.route('/register', methods=['POST'])
def register():
payload = request.get_json()

# since emails are case insensitive in the world..

payload['email'] = payload['email'].lower()
payload['username'] = payload['username'].lower()
# print(payload)

try:
# see if user exists
# if they do then we do not want to create the user
# returning a msg that they cant
models.User.get(models.User.email == payload['email'] and models.User.username == payload['username'])
# this will throw an error [models.DoesNotExist 'exception'] if they do not exist
# if that query doesn't cause that error
# which in our case means we can go ahead and register them
return jsonify(
data={},
message=f'A user with that email already exists',
status=401
), 401


# but if we get the error then the user is not found (does not exist)
# then we can register this user
except models.DoesNotExist:# is like catch in JS

# in this except we are safe to create user

created_user = models.User.create(
username=payload['username'],
email=payload['email'],
password=generate_password_hash(payload['password'])
)

# this is where actually use flask
# this logs in the user and starts the session


# we can jsonify password and there is no reason to
# send this back to user
#In Python 3, you need to use decode(‘utf-8’) on generate_password_hash(), like below:
#pw_hash = bcrypt.generate_password_hash(‘hunter2’).decode(‘utf-8’)
# print(f' here is that new users with hashed pw {model_to_dict(created_user)}')
user_dict = model_to_dict(created_user)
user_dict.pop('password')
return jsonify(
data=user_dict,
message=f'Succesfully created a user! Email is {user_dict}',
status=400
), 400

@users.route('/login', methods=['POST'])
def login():

payload = request.get_json()

payload['email'] = payload['email'].lower()
payload['username'] = payload['username'].lower()

try:
user = models.User.get(models.User.email == payload['email'] or models.User.username == payload['username'])
# look up user by email
# if we didn't cause a models
#does not exist, then lets check their password
user_dict = model_to_dict(user)

### check user password hash with bcrypt ###
# you are checking the encrytped password you looked up and the second
# one is the one that was typed by the user
password_is_good = check_password_hash(user_dict['password'], payload['password'])
if password_is_good:
# if true the user should be logged in
# this is how you do log user in
login_user(user)

user_dict.pop('password')

return jsonify(
data=user_dict,
message='Succesfully logged in as {}'.format(user_dict['email'])
), 200
else:
print('password is invalid')
return jsonify(
data={},
message='Email or password is incorrect',
status=401
), 401


except models.DoesNotExist: # it mean user not found
print('username is no good')
return jsonify(
date={},
message='Email or password is incorrect',
status=401
), 401
@users.route('/all', methods=['GET'])
def get_user_index():
users = models.User.select()

user_dicts = [model_to_dict(u) for u in users]

# delete passwords
# excuse how map works in python
# define a callback to be run on every dict in user dicts
def remove_password(u):
u.pop('password')
return u

user_dicts_without_pw = map(remove_password, user_dicts)

return jsonify(data=list(user_dicts_without_pw)), 200

# route that will take an id and let us create a dog associated
# with the owner that has that id

# teaching to tool -- route to show which user is logged in
# demo on how to use current_user, this required user_loader
# to be set up in app.py

@users.route('/logged_in', methods=['GET'])
def get_logged_in_user():
print(current_user) # this is the user who is logged in
print(type(current_user)) # <class 'werkzeug.local.LocalProxy'>

user_dict = model_to_dict(current_user)
print(user_dict)
return jsonify(
data=user_dict,
message='This is who is logged in',
status=200
), 200

# user will still be logged in even after the server is restarted
#
@users.route('/logout', methods=['GET'])
def logout():
logout_user()
return jsonify(
data={},
message='You are succesfully logged out',
status=200
), 200

0 comments on commit 5d45453

Please sign in to comment.