user roles and permissions

This commit is contained in:
rimu 2023-10-18 22:23:59 +13:00
parent 5aa7320bea
commit 4b916fcf86
5 changed files with 170 additions and 27 deletions

View file

@ -6,7 +6,9 @@ from app import db
import click
import os
from app.models import Settings, BannedInstances, Interest
from app.auth.email import send_verification_email
from app.auth.util import random_token
from app.models import Settings, BannedInstances, Interest, Role, User, RolePermission
from app.utils import file_get_contents
@ -48,33 +50,63 @@ def register(app):
db.drop_all()
db.configure_mappers()
db.create_all()
db.session.append(Settings(name='allow_nsfw', value=json.dumps(False)))
db.session.append(Settings(name='allow_nsfl', value=json.dumps(False)))
db.session.append(Settings(name='allow_dislike', value=json.dumps(True)))
db.session.append(Settings(name='allow_local_image_posts', value=json.dumps(True)))
db.session.append(Settings(name='allow_remote_image_posts', value=json.dumps(True)))
db.session.append(Settings(name='registration_open', value=json.dumps(True)))
db.session.append(Settings(name='approve_registrations', value=json.dumps(False)))
db.session.append(Settings(name='federation', value=json.dumps(True)))
db.session.append(BannedInstances(domain='lemmygrad.ml'))
db.session.append(BannedInstances(domain='gab.com'))
db.session.append(BannedInstances(domain='rqd2.net'))
db.session.append(BannedInstances(domain='exploding-heads.com'))
db.session.append(BannedInstances(domain='hexbear.net'))
db.session.append(BannedInstances(domain='threads.net'))
db.session.add(Settings(name='allow_nsfw', value=json.dumps(False)))
db.session.add(Settings(name='allow_nsfl', value=json.dumps(False)))
db.session.add(Settings(name='allow_dislike', value=json.dumps(True)))
db.session.add(Settings(name='allow_local_image_posts', value=json.dumps(True)))
db.session.add(Settings(name='allow_remote_image_posts', value=json.dumps(True)))
db.session.add(Settings(name='registration_open', value=json.dumps(True)))
db.session.add(Settings(name='approve_registrations', value=json.dumps(False)))
db.session.add(Settings(name='federation', value=json.dumps(True)))
db.session.add(BannedInstances(domain='lemmygrad.ml'))
db.session.add(BannedInstances(domain='gab.com'))
db.session.add(BannedInstances(domain='rqd2.net'))
db.session.add(BannedInstances(domain='exploding-heads.com'))
db.session.add(BannedInstances(domain='hexbear.net'))
db.session.add(BannedInstances(domain='threads.net'))
interests = file_get_contents('interests.txt')
db.session.append(Interest(name='🕊 Chilling', communities=parse_communities(interests, 'chilling')))
db.session.append(Interest(name='💭 Interesting stuff', communities=parse_communities(interests, 'interesting stuff')))
db.session.append(Interest(name='📰 News & Politics', communities=parse_communities(interests, 'news & politics')))
db.session.append(Interest(name='🎮 Gaming', communities=parse_communities(interests, 'gaming')))
db.session.append(Interest(name='🤓 Linux', communities=parse_communities(interests, 'linux')))
db.session.append(Interest(name='♻️ Environment', communities=parse_communities(interests, 'environment')))
db.session.append(Interest(name='🏳‍🌈 LGBTQ+', communities=parse_communities(interests, 'lgbtq')))
db.session.append(Interest(name='🛠 Programming', communities=parse_communities(interests, 'programming')))
db.session.append(Interest(name='🖥️ Tech', communities=parse_communities(interests, 'tech')))
db.session.append(Interest(name='🤗 Mental Health', communities=parse_communities(interests, 'mental health')))
db.session.add(Interest(name='🕊 Chilling', communities=parse_communities(interests, 'chilling')))
db.session.add(Interest(name='💭 Interesting stuff', communities=parse_communities(interests, 'interesting stuff')))
db.session.add(Interest(name='📰 News & Politics', communities=parse_communities(interests, 'news & politics')))
db.session.add(Interest(name='🎮 Gaming', communities=parse_communities(interests, 'gaming')))
db.session.add(Interest(name='🤓 Linux', communities=parse_communities(interests, 'linux')))
db.session.add(Interest(name='♻️ Environment', communities=parse_communities(interests, 'environment')))
db.session.add(Interest(name='🏳‍🌈 LGBTQ+', communities=parse_communities(interests, 'lgbtq')))
db.session.add(Interest(name='🛠 Programming', communities=parse_communities(interests, 'programming')))
db.session.add(Interest(name='🖥️ Tech', communities=parse_communities(interests, 'tech')))
db.session.add(Interest(name='🤗 Mental Health', communities=parse_communities(interests, 'mental health')))
# Initial roles
anon_role = Role(name='Anonymous user', weight=0)
anon_role.permissions.append(RolePermission(permission='register'))
db.session.add(anon_role)
auth_role = Role(name='Authenticated user', weight=1)
db.session.add(auth_role)
staff_role = Role(name='Staff', weight=2)
staff_role.permissions.append(RolePermission(permission='approve registrations'))
staff_role.permissions.append(RolePermission(permission='manage users'))
db.session.add(staff_role)
admin_role = Role(name='Admin', weight=3)
admin_role.permissions.append(RolePermission(permission='change user roles'))
admin_role.permissions.append(RolePermission(permission='manage users'))
db.session.add(admin_role)
# Admin user
user_name = input("Admin user name (ideally not 'admin'): ")
email = input("Admin email address: ")
password = input("Admin password: ")
verification_token = random_token(16)
admin_user = User(user_name=user_name, email=email, verification_token=verification_token)
admin_user.set_password(password)
admin_user.roles.append(admin_role)
send_verification_email(admin_user)
print("Check your email inbox for a verification link.")
db.session.commit()
print("Done")
print("Initial setup is finished.")
def parse_communities(interests_source, segment):

View file

@ -8,6 +8,7 @@ POST_TYPE_POLL = 5
DATETIME_MS_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
# Community subscription levels
SUBSCRIPTION_OWNER = 3
SUBSCRIPTION_MODERATOR = 2
SUBSCRIPTION_MEMBER = 1

View file

@ -113,6 +113,13 @@ class Community(db.Model):
).all()
user_role = db.Table('user_role',
db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
db.Column('role_id', db.Integer, db.ForeignKey('role.id')),
db.PrimaryKeyConstraint('user_id', 'role_id')
)
class User(UserMixin, db.Model):
query_class = FullTextSearchQuery
id = db.Column(db.Integer, primary_key=True)
@ -129,7 +136,6 @@ class User(UserMixin, db.Model):
show_nsfl = db.Column(db.Boolean, default=False)
created = db.Column(db.DateTime, default=datetime.utcnow)
last_seen = db.Column(db.DateTime, default=datetime.utcnow, index=True)
role = db.Column(db.Integer, default=0)
avatar_id = db.Column(db.Integer, db.ForeignKey('file.id'))
cover_id = db.Column(db.Integer, db.ForeignKey('file.id'))
public_key = db.Column(db.Text)
@ -164,6 +170,8 @@ class User(UserMixin, db.Model):
posts = db.relationship('Post', backref='author', lazy='dynamic', cascade="all, delete-orphan")
post_replies = db.relationship('PostReply', backref='author', lazy='dynamic', cascade="all, delete-orphan")
roles = db.relationship('Role', secondary=user_role, lazy='dynamic', cascade="all, delete")
def __repr__(self):
return '<User {}>'.format(self.user_name)
@ -489,6 +497,17 @@ class FilterKeyword(db.Model):
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
class Role(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
weight = db.Column(db.Integer, default=0)
permissions = db.relationship('RolePermission')
class RolePermission(db.Model):
role_id = db.Column(db.Integer, db.ForeignKey('role.id'), primary_key=True)
permission = db.Column(db.String, primary_key=True, index=True)
@login.user_loader
def load_user(id):

View file

@ -0,0 +1,38 @@
"""user roles additional
Revision ID: 882e33231c5b
Revises: f1f0c854ae18
Create Date: 2023-10-18 22:10:16.602027
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '882e33231c5b'
down_revision = 'f1f0c854ae18'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('role_permission', schema=None) as batch_op:
batch_op.create_foreign_key(None, 'role', ['role_id'], ['id'])
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.drop_column('role')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('role', sa.INTEGER(), autoincrement=False, nullable=True))
with op.batch_alter_table('role_permission', schema=None) as batch_op:
batch_op.drop_constraint(None, type_='foreignkey')
# ### end Alembic commands ###

View file

@ -0,0 +1,53 @@
"""user roles permissions
Revision ID: f1f0c854ae18
Revises: e82f86c550ac
Create Date: 2023-10-18 21:39:43.281172
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'f1f0c854ae18'
down_revision = 'e82f86c550ac'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('role',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=50), nullable=True),
sa.Column('weight', sa.Integer(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_table('role_permission',
sa.Column('role_id', sa.Integer(), nullable=False),
sa.Column('permission', sa.String(), nullable=False),
sa.PrimaryKeyConstraint('role_id', 'permission')
)
with op.batch_alter_table('role_permission', schema=None) as batch_op:
batch_op.create_index(batch_op.f('ix_role_permission_permission'), ['permission'], unique=False)
op.create_table('user_role',
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('role_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['role_id'], ['role.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('user_id', 'role_id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('user_role')
with op.batch_alter_table('role_permission', schema=None) as batch_op:
batch_op.drop_index(batch_op.f('ix_role_permission_permission'))
op.drop_table('role_permission')
op.drop_table('role')
# ### end Alembic commands ###