diff --git a/login/app.py b/login/app.py index daf184e734df187b0c4563edfeb79ce47ba7ef06..c282165644339f6b28df11aa4c96802019aeec91 100644 --- a/login/app.py +++ b/login/app.py @@ -85,7 +85,7 @@ Migrate(app, db) # Import needs to happen after the database interface is created. AppRole is # imported for future usage # pylint: disable=wrong-import-position unused-import -from models import User, App, AppRole +from models import App, AppRole # # WARNING: @@ -160,6 +160,51 @@ app.cli.add_command(app_cli) ## CLI USER COMMANDS +@user_cli.command('setrole') +@click.argument('email') +@click.argument('app_slug') +@click.argument('role') +def setrole(email, app_slug, role): + app.logger.info(f"Assiging role {role} to {email} for app {app_slug}"); + + # Find user + user = KratosUser.find_by_email(KRATOS_ADMIN, email) + + if role != 'admin' and role != 'user': + print("At this point only the roles 'admin' and 'user' are accepted"); + exit(1) + + + + if not user: + print("User not found. Abort"); + exit(1) + + app_obj = db.session.query(App).filter(App.slug==app_slug).first() + if not app_obj: + print("App not found. Abort."); + exit(1) + + + role_obj = db.session.query(AppRole).\ + filter(AppRole.app_id==app_obj.id).\ + filter(AppRole.user_id==user.uuid).first() + + + if role_obj: + db.session.delete(role_obj) + + obj = AppRole() + obj.user_id = user.uuid + obj.app_id = app_obj.id + obj.role = role + + + db.session.add(obj) + db.session.commit() + + + @user_cli.command('show') @click.argument('email') def show_user(email): @@ -493,6 +538,18 @@ def consent(): app.logger.error(f"User not found in database: {kratos_id}") abort(401, description="User not found. Please try again.") + # Get role on this app + app_obj = db.session.query(App).filter(App.slug==app_name).first() + + # Default access level + role = 'user' + if app_obj: + role_obj = db.session.query(AppRole).\ + filter(AppRole.app_id==app_obj.id).\ + filter(AppRole.user_id==user.uuid).first() + if role_obj: + role = role_obj.role + # Get claims for this user, provided the current app claims = user.get_claims(app_name) diff --git a/login/migrations/versions/4cdc1d4ed8d1_.py b/login/migrations/versions/27761560bbcb_.py similarity index 62% rename from login/migrations/versions/4cdc1d4ed8d1_.py rename to login/migrations/versions/27761560bbcb_.py index bfd4def6c75246ee797f2d6fa1b18c3612886622..2d0fc180a2bca81c5c34f1f5fc3d5dc60db68a11 100644 --- a/login/migrations/versions/4cdc1d4ed8d1_.py +++ b/login/migrations/versions/27761560bbcb_.py @@ -1,8 +1,8 @@ """empty message -Revision ID: 4cdc1d4ed8d1 +Revision ID: 27761560bbcb Revises: -Create Date: 2021-11-18 11:46:33.222668 +Create Date: 2021-12-21 06:07:14.857940 """ from alembic import op @@ -10,7 +10,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision = '4cdc1d4ed8d1' +revision = '27761560bbcb' down_revision = None branch_labels = None depends_on = None @@ -25,21 +25,11 @@ def upgrade(): sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('slug') ) - op.create_table('user', - sa.Column('id', sa.Integer(), nullable=False), - sa.Column('email', sa.String(), nullable=True), - sa.Column('kratos_id', sa.String(), nullable=True), - sa.Column('admin', sa.Boolean(), nullable=True), - sa.PrimaryKeyConstraint('id'), - sa.UniqueConstraint('email'), - sa.UniqueConstraint('kratos_id') - ) op.create_table('app_role', - sa.Column('user_id', sa.Integer(), nullable=False), + sa.Column('user_id', sa.String(), nullable=False), sa.Column('app_id', sa.Integer(), nullable=False), sa.Column('role', sa.String(), nullable=True), sa.ForeignKeyConstraint(['app_id'], ['app.id'], ), - sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), sa.PrimaryKeyConstraint('user_id', 'app_id') ) # ### end Alembic commands ### @@ -48,6 +38,5 @@ def upgrade(): def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.drop_table('app_role') - op.drop_table('user') op.drop_table('app') # ### end Alembic commands ### diff --git a/login/models.py b/login/models.py index 07bb55822e68454d932e7c1f7967a9a9975fc4c6..de62e608d620fd49f0fbb583d3436ce0675a98c2 100644 --- a/login/models.py +++ b/login/models.py @@ -11,23 +11,6 @@ from sqlalchemy import Integer, String, ForeignKey, Boolean # This is based on the documentation of Flask Alchemy from app import db -# Pylint complains about too-few-public-methods. Methods will be added once -# this is implemented. -# pylint: disable=too-few-public-methods -class User(db.Model): - """ - Represents a user in Kratos as well as this application's database. - """ - - id = db.Column(Integer, primary_key=True) - email = db.Column(String, unique=True) - kratos_id = db.Column(String, unique=True) - admin = db.Column(Boolean, default=False) - - def __repr__(self): - return f"{self.id} <{self.email}>" - - # Pylint complains about too-few-public-methods. Methods will be added once # this is implemented. # pylint: disable=too-few-public-methods @@ -53,11 +36,13 @@ class AppRole(db.Model): The AppRole object, stores the roles Users have on Apps """ - user_id = db.Column(Integer, ForeignKey('user.id'), primary_key=True) + user_id = db.Column(String, primary_key=True) app_id = db.Column(Integer, ForeignKey('app.id'), primary_key=True) -# user = relationship("User", back_populates="approle") -# app = relationship("App") - role = db.Column(String) + + def __repr__(self): + return f"{self.role} for {self.user_id} on {self.app_id}" + +