0

I have the weirdest behavior while using flask-sqlalchemy, I have a User model and I have an enum with the user role as userrole, it has the following values ('vendor', 'vendor_admin', 'admin', 'collector', 'retailer'), the weird thing is that whenever I query the users I get all the roles as string except the admin for some reason it comes as a list with the value admin.

I've deleted the database and re-migrated everything from scratch but still.

Here is my User model:

from app import db, ma
from marshmallow_enum import EnumField
import enum
import bcrypt


class UserRoleEnum(enum.Enum):
    admin = 'admin',
    collector = 'collector'
    retailer = 'retailer'
    vendor = 'vendor'
    vendor_admin = 'vendor_admin'


class User(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(), nullable=False)
    mobile = db.Column(db.String(), nullable=False, unique=True)
    username = db.Column(db.String(), unique=True, nullable=False)
    password = db.Column(db.TEXT(), nullable=False)
    is_active = db.Column(db.Boolean(), default=False)
    role = db.Column(db.Enum(UserRoleEnum), nullable=False)
    created_on = db.Column(db.DateTime, server_default=db.func.now())
    updated_on = db.Column(db.DateTime, server_default=db.func.now(), server_onupdate=db.func.now())

    # relations

    #related fields
    organization_id = db.Column(db.Integer, db.ForeignKey('organizations.id'), nullable=True)
    invoices = db.relationship('Invoice', backref='user')

    def __init__(
            self,
            name,
            username,
            mobile,
            password,
            role,
            is_active,
            organization_id = None
    ):
        self.name = name
        self.username = username
        self.mobile = mobile
        self.role = role
        self.is_active = is_active
        self.organization_id = organization_id
        self.password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode()

    def __repr__(self):
        return "<id %s>" % self.id


class UserSchema(ma.SQLAlchemyAutoSchema):
    role = EnumField(UserRoleEnum, by_value=True)
    class Meta:
        exclude = ['password']
        model = User
        load_instance = True

Here is the login endpoint:

@auth_routes.route('login', methods=['POST'])
def login():
    payload = request.json

    if not payload.get('mobile') or not payload.get('password'):
        return "Mobile and Password are required", 400

    user = User.query.filter_by(mobile=payload.get('mobile')).first()

    if not user:
        return "User not found", 404

    if bcrypt.checkpw(payload.get('password').encode('utf-8'), user.password.encode('utf-8')):

        organization = None

        if user.organization_id:
            organization = OrganizationSchema().dump(Organization.query.get(user.organization_id)).data

        token = create_access_token(identity={
            'id': user.id,
            'username': user.username,
            'mobile': user.mobile,
            'is_active': user.is_active,
            'role': user.role.value,
            'organization': organization
        }, expires_delta=timedelta(days=0) + timedelta(days=365))
        return {
            "token": token
        }
    else:
        return "Error on password"

Here is an example from the terminal:

>>> user = User.query.get(1)
>>> user.role.value
('admin',)
>>> user = User.query.get(2)
>>> user.role.value
'vendor_admin'
0

1 Answer 1

3

You have a trailing comma so admin value is a tuple

class UserRoleEnum(enum.Enum):
    admin = 'admin',

Remove it and all will be fine

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, didn't notice the typo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.