Tri
Tri

Reputation: 3039

Flask-Admin set up default user roles when register

I making a dashboard with Flask-Admin and using Flask-SQLAlchemy for my models, like this:

roles_users = db.Table(
    'roles_users',
    db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
    db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))
)

class Role(db.Model, RoleMixin):
    __tablename__ = 'role'
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255))
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))

I want when user register with Flask-Admin, the default role for the user has set up to client. enter image description here

I have try something like this on roles column:

roles = db.relationship('Role', secondary=roles_users,
                     backref=db.backref('users', lazy='dynamic'),
                     default='client') # or default=3 (which is '3' is the client id in roles_user association table.

But I got this message:

TypeError: relationship() got an unexpected keyword argument 'default'

And I have also tried this solution But now working for me.

So, is it possible to set default role when user register..?

NOTE: In the other case, I also ask very similar with this question here, but there are in different case. There I want the role are set up when I making a new user by superuser, not when users register by their own.

Upvotes: 1

Views: 2002

Answers (3)

lator
lator

Reputation: 345

All the answers provided have come from having to use Flask-Security. In the case that you don't want to use Flask-Security because of its bloatedness or for some other reason, you can do this in your models.py file

from passlib.hash import sha256_crypt


#Assuming that you have an initialised 'db' object

users_x_roles = db.Table(
    "users_roles",
    db.Column("user_id", db.ForeignKey("user.id_")),
    db.Column("role_id", db.ForeignKey("role.id_")),
    db.Column("assigned_at", db.DateTime, default=datetime.utcnow)
)


class Role(db.Model):

    id_ = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True, nullable=False)
    description = db.Column(db.String(255))

    users = db.relationship("User", secondary="users_roles", back_populates="roles")

    def __init__(self, role_name: str, role_description: str):
        self.name = role_name
        self.description = role_description

    def __repr__(self):
        return f"<Role: {self.name}>"

    def __str__(self):
        return self.name


class User(db.Model, UserMixin):

    id_ = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(20), nullable=False, unique=True)
    email = db.Column(db.String(50), nullable=False, unique=True)
    password = db.Column(db.String(500), nullable=False)

    roles = db.relationship("Role", secondary="users_roles", back_populates="users")

    def __init__(self, username, email, password):
        self.username = username
        self.email = email
        self.password = password

        default_role = Role.query.filter_by(name="regular").first()
        if default_role:
            self.roles.append(default_role)
        else:
            new_default_role = Role(role_name="regular", role_description="Can comment, can create post.")
            self.roles.append(new_default_role)

    def __repr__(self) -> str:
        return f"<User: {self.email}>"

    @property
    def is_authenticated(self):
        return super().is_authenticated

    @property
    def is_active(self):
        return super().is_active

    @property
    def is_admin(self):
        admin_role = Role.query.filter_by(name="admin").first()
        return admin_role in self.roles

    def get_id(self):
        return self.id_

    def password_is_correct(self, password_candidate: str):
        return sha256_crypt.verify(password_candidate, self.password)

Hope this helps.

Upvotes: 1

gittert
gittert

Reputation: 1308

I use this code during app initialization:

@user_registered.connect_via(app)     
def user_registered_sighandler(app, user, confirm_token):               
    default_role = user_datastore.find_role("user")         
    user_datastore.add_role_to_user(user, default_role)            
    db.session.commit()

The above implementation comes from flask-security

Upvotes: 2

Tri
Tri

Reputation: 3039

I modifying @gitter code, so here the worked code for my case:

@user_registered.connect_via(app)
    def user_registered_sighandler(app, user, confirm_token):
        default_role = Role.query.filter_by(name='client').first()
        user.roles.append(default_role)
        db.session.commit()

Thanks @gitter, you made some insight for me to do it.

Upvotes: 0

Related Questions