mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
user roles and permissions
This commit is contained in:
parent
5aa7320bea
commit
4b916fcf86
5 changed files with 170 additions and 27 deletions
84
app/cli.py
84
app/cli.py
|
@ -6,7 +6,9 @@ from app import db
|
||||||
import click
|
import click
|
||||||
import os
|
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
|
from app.utils import file_get_contents
|
||||||
|
|
||||||
|
|
||||||
|
@ -48,33 +50,63 @@ def register(app):
|
||||||
db.drop_all()
|
db.drop_all()
|
||||||
db.configure_mappers()
|
db.configure_mappers()
|
||||||
db.create_all()
|
db.create_all()
|
||||||
db.session.append(Settings(name='allow_nsfw', value=json.dumps(False)))
|
db.session.add(Settings(name='allow_nsfw', value=json.dumps(False)))
|
||||||
db.session.append(Settings(name='allow_nsfl', value=json.dumps(False)))
|
db.session.add(Settings(name='allow_nsfl', value=json.dumps(False)))
|
||||||
db.session.append(Settings(name='allow_dislike', value=json.dumps(True)))
|
db.session.add(Settings(name='allow_dislike', value=json.dumps(True)))
|
||||||
db.session.append(Settings(name='allow_local_image_posts', value=json.dumps(True)))
|
db.session.add(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.add(Settings(name='allow_remote_image_posts', value=json.dumps(True)))
|
||||||
db.session.append(Settings(name='registration_open', value=json.dumps(True)))
|
db.session.add(Settings(name='registration_open', value=json.dumps(True)))
|
||||||
db.session.append(Settings(name='approve_registrations', value=json.dumps(False)))
|
db.session.add(Settings(name='approve_registrations', value=json.dumps(False)))
|
||||||
db.session.append(Settings(name='federation', value=json.dumps(True)))
|
db.session.add(Settings(name='federation', value=json.dumps(True)))
|
||||||
db.session.append(BannedInstances(domain='lemmygrad.ml'))
|
db.session.add(BannedInstances(domain='lemmygrad.ml'))
|
||||||
db.session.append(BannedInstances(domain='gab.com'))
|
db.session.add(BannedInstances(domain='gab.com'))
|
||||||
db.session.append(BannedInstances(domain='rqd2.net'))
|
db.session.add(BannedInstances(domain='rqd2.net'))
|
||||||
db.session.append(BannedInstances(domain='exploding-heads.com'))
|
db.session.add(BannedInstances(domain='exploding-heads.com'))
|
||||||
db.session.append(BannedInstances(domain='hexbear.net'))
|
db.session.add(BannedInstances(domain='hexbear.net'))
|
||||||
db.session.append(BannedInstances(domain='threads.net'))
|
db.session.add(BannedInstances(domain='threads.net'))
|
||||||
interests = file_get_contents('interests.txt')
|
interests = file_get_contents('interests.txt')
|
||||||
db.session.append(Interest(name='🕊 Chilling', communities=parse_communities(interests, 'chilling')))
|
db.session.add(Interest(name='🕊 Chilling', communities=parse_communities(interests, 'chilling')))
|
||||||
db.session.append(Interest(name='💭 Interesting stuff', communities=parse_communities(interests, 'interesting stuff')))
|
db.session.add(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.add(Interest(name='📰 News & Politics', communities=parse_communities(interests, 'news & politics')))
|
||||||
db.session.append(Interest(name='🎮 Gaming', communities=parse_communities(interests, 'gaming')))
|
db.session.add(Interest(name='🎮 Gaming', communities=parse_communities(interests, 'gaming')))
|
||||||
db.session.append(Interest(name='🤓 Linux', communities=parse_communities(interests, 'linux')))
|
db.session.add(Interest(name='🤓 Linux', communities=parse_communities(interests, 'linux')))
|
||||||
db.session.append(Interest(name='♻️ Environment', communities=parse_communities(interests, 'environment')))
|
db.session.add(Interest(name='♻️ Environment', communities=parse_communities(interests, 'environment')))
|
||||||
db.session.append(Interest(name='🏳🌈 LGBTQ+', communities=parse_communities(interests, 'lgbtq')))
|
db.session.add(Interest(name='🏳🌈 LGBTQ+', communities=parse_communities(interests, 'lgbtq')))
|
||||||
db.session.append(Interest(name='🛠 Programming', communities=parse_communities(interests, 'programming')))
|
db.session.add(Interest(name='🛠 Programming', communities=parse_communities(interests, 'programming')))
|
||||||
db.session.append(Interest(name='🖥️ Tech', communities=parse_communities(interests, 'tech')))
|
db.session.add(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='🤗 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()
|
db.session.commit()
|
||||||
print("Done")
|
print("Initial setup is finished.")
|
||||||
|
|
||||||
|
|
||||||
def parse_communities(interests_source, segment):
|
def parse_communities(interests_source, segment):
|
||||||
|
|
|
@ -8,6 +8,7 @@ POST_TYPE_POLL = 5
|
||||||
|
|
||||||
DATETIME_MS_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
|
DATETIME_MS_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"
|
||||||
|
|
||||||
|
# Community subscription levels
|
||||||
SUBSCRIPTION_OWNER = 3
|
SUBSCRIPTION_OWNER = 3
|
||||||
SUBSCRIPTION_MODERATOR = 2
|
SUBSCRIPTION_MODERATOR = 2
|
||||||
SUBSCRIPTION_MEMBER = 1
|
SUBSCRIPTION_MEMBER = 1
|
||||||
|
|
|
@ -113,6 +113,13 @@ class Community(db.Model):
|
||||||
).all()
|
).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):
|
class User(UserMixin, db.Model):
|
||||||
query_class = FullTextSearchQuery
|
query_class = FullTextSearchQuery
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
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)
|
show_nsfl = db.Column(db.Boolean, default=False)
|
||||||
created = db.Column(db.DateTime, default=datetime.utcnow)
|
created = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
last_seen = db.Column(db.DateTime, default=datetime.utcnow, index=True)
|
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'))
|
avatar_id = db.Column(db.Integer, db.ForeignKey('file.id'))
|
||||||
cover_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)
|
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")
|
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")
|
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):
|
def __repr__(self):
|
||||||
return '<User {}>'.format(self.user_name)
|
return '<User {}>'.format(self.user_name)
|
||||||
|
|
||||||
|
@ -489,6 +497,17 @@ class FilterKeyword(db.Model):
|
||||||
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
|
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
|
@login.user_loader
|
||||||
def load_user(id):
|
def load_user(id):
|
||||||
|
|
38
migrations/versions/882e33231c5b_user_roles_additional.py
Normal file
38
migrations/versions/882e33231c5b_user_roles_additional.py
Normal 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 ###
|
53
migrations/versions/f1f0c854ae18_user_roles_permissions.py
Normal file
53
migrations/versions/f1f0c854ae18_user_roles_permissions.py
Normal 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 ###
|
Loading…
Add table
Reference in a new issue