Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Flask REST API API Protection Password hashing

Bummer: Didn't get back a properly hashed password; `User.hash_password` should be a static method

I keep getting the following Bummer message for Task 3 of 3.

models.py
import datetime

from argon2 import PasswordHasher
from itsdangerous import (TimedJSONWebSignatureSerializer as Serializer,
                          BadSignature, SignatureExpired)
from peewee import *

DATABASE = SqliteDatabase('courses.sqlite')
HASHER = PasswordHasher()


class User(Model):
    username = CharField(unique=True)
    email = CharField(unique=True)
    password = CharField()

    class Meta:
        database = DATABASE

    @classmethod
    def create_user(cls, username, email, password, **kwargs):
        email = email.lower()
        try:
            cls.select().where(
                (cls.email == email) | (cls.username**username)
            ).get()
        except cls.DoesNotExist:
            user = cls(username=username, email=email)
            user.password = user.set_password(password)
            user.save()
            return user
        else:
            raise Exception("User with that email or username already exists.")

    @staticmethod
    def verify_auth_token(token):
        serializer = Serializer(config.SECRET_KEY)
        try:
            data = serializer.loads(token)
        except (SignatureExpired, BadSignature):
            return None
        else:
            user = User.get(User.id == data['id'])
            return user

    @staticmethod 
    def set_password(password): 
        return HASHER.hash(password)

    def verify_password(self, password):
        return HASHER.verify(self.password, password)

    def generate_auth_token(self, expires=3600):
        serializer = Serializer(config.SECRET_KEY, expires_in=expires)
        return serializer.dumps({'id': self.id})


class Course(Model):
    title = CharField()
    url = CharField(unique=True)
    created_at = DateTimeField(default=datetime.datetime.now)

    class Meta:
        database = DATABASE


class Review(Model):
    course = ForeignKeyField(Course, related_name='review_set')
    rating = IntegerField()
    comment = TextField(default='')
    created_at = DateTimeField(default=datetime.datetime.now)
    created_by = ForeignKeyField(User, related_name='review_set')

    class Meta:
        database = DATABASE


def initialize():
    DATABASE.connect()
    DATABASE.create_tables([User, Course, Review], safe=True)
    DATABASE.close()

2 Answers

Brandon Oakes
seal-mask
.a{fill-rule:evenodd;}techdegree
Brandon Oakes
Python Web Development Techdegree Student 11,501 Points

So I am not sure where you got some of your code but you were suppose to make a hash_password function that is a static method for task 2 of 3. It would look something like this:

             @staticmethod   
             def hash_password(password):
             return HASHER.hash(password)

BUT it looks like your set_password is the same thing. Try changing this line.

            user.password = user.set_password(password)

to this:

            user.password = cls.set_password(password)

The reason you change the user to cls is because the user instance has not been created yet so it can not call the hash password method. Let me know if this works and more importantly if my explanation made sense. Good luck

import datetime from argon2 import PasswordHasher from itsdangerous import (TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired) from peewee import * DATABASE = SqliteDatabase('courses.sqlite') HASHER = PasswordHasher()

class Course(Model): title = CharField() url = CharField(unique=True) created_at = DateTimeField(default=datetime.datetime.now)

class Meta:
    database = DATABASE

class Review(Model): course = ForeignKeyField(Course, related_name='review_set') rating = IntegerField() comment = TextField(default='') created_at = DateTimeField(default=datetime.datetime.now) created_by = ForeignKeyField(User, related_name='review_set')

class Meta:
    database = DATABASE

class User(Model): username = CharField(unique=True) email = CharField(unique=True) password = CharField()

class Meta:
    database = DATABASE

@classmethod
def create_user(cls, username, email, password, **kwargs):
    email = email.lower()
    try:
        cls.select().where(
            (cls.email == email) | (cls.username**username)
        ).get()
    except cls.DoesNotExist:
        user = cls(username=username, email=email)
        user.password = cls.set_password(password)
        user.save()
        return user
    else:
        raise Exception("User with that email or username already exists.")

@staticmethod 
def hash_password(password): 
    return HASHER.hash(password)

def verify_password(self, password):
    return HASHER.verify(self.password, password)  

def initialize(): DATABASE.connect() DATABASE.create_tables([User, Course, Review], safe=True) DATABASE.close()

I now receive an error message...............Bummer: name 'User' is not defined

Brandon Oakes
seal-mask
.a{fill-rule:evenodd;}techdegree
Brandon Oakes
Python Web Development Techdegree Student 11,501 Points

The question wants you to make a static method and then apply it to the user.password. It wants you to call the method with the class object through: user.password = cls.hash_password(password). The code below works.

import datetime

from peewee import *

from argon2 import PasswordHasher

DATABASE = SqliteDatabase('recipes.db')

HASHER = PasswordHasher()

class User(Model): username = CharField(unique=True) password = CharField()

class Meta:
    database = DATABASE

@classmethod
def create_user(cls, username, password):
    try:
        cls.get(cls.username**username)
    except cls.DoesNotExist:
        user = cls(username=username)
        user.password = cls.hash_password(password) #Here the class instance is calling the static method we just made
        user.save()
        return user
    else:
        raise Exception("User already exists")  

@staticmethod
def hash_password(password):   #function takes in user password and hashes it
    return HASHER.hash(password)



class Recipe(Model):
    name = CharField()
    created_at = DateTimeField(default=datetime.datetime.now)

    class Meta:
        database = DATABASE


class Ingredient(Model):
    name = CharField()
    description = CharField()
    quantity = DecimalField()
    measurement_type = CharField()
    recipe = ForeignKeyField(Recipe)

class Meta:
    database = DATABASE


def initialize():
    DATABASE.connect()
    DATABASE.create_tables([User, Recipe, Ingredient], safe=True)
    DATABASE.close(

Hey I used your code(because I was also having trouble with this code challenge) and it says "Bummer: cannot import name 'User'" and not passing...any suggestions?