diff --git a/app/models.py b/app/models.py index 3f7bc82..c794eaf 100644 --- a/app/models.py +++ b/app/models.py @@ -17,6 +17,24 @@ def utc_now(): return datetime.now(UTC()) +class UserActiveStatusChange(db.Model): + __tablename__ = "users_active_status_changes" + id = db.Column(db.Integer, primary_key=True) + id_user = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) + status = db.Column(db.String(10), nullable=False, default="inactive") + date = db.Column(db.DateTime, default=utc_now) + user = db.relationship("User", backref="status_changes") + + +"""Allow for the creation of one or more roles with attributes +role_id, role_name, and department_name. +Combination of role_name and department_name is unique +Allow for a user to be assigned one or more roles +and for a role to be assigned to one or more users. +Users_roles table relies on roles_lookup +for putting a name and dept to a role id.""" + + class User(db.Model): __tablename__ = "users" id = db.Column(db.Integer, primary_key=True) @@ -26,16 +44,40 @@ class User(db.Model): active = db.Column(db.Boolean, default=False) # Issue 02-Active users access_level = db.Column( db.String(16), default="basic", nullable=False - ) # "Role" - Issue 03-Access levels + ) # Kept as requested + + # Establish the many-to-many relationship with roles + roles = db.relationship( + "RolesLookup", secondary="users_roles", back_populates="users" + ) def __repr__(self): return f"" -class UserActiveStatusChange(db.Model): - __tablename__ = "users_active_status_changes" +class UserRole(db.Model): + __tablename__ = "users_roles" id = db.Column(db.Integer, primary_key=True) - id_user = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) - status = db.Column(db.String(10), nullable=False, default="inactive") - date = db.Column(db.DateTime, default=utc_now) - user = db.relationship("User", backref="status_changes") + user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) + role_id = db.Column(db.Integer, db.ForeignKey("roles_lookup.id"), nullable=False) + + # Add unique constraint to prevent duplicate user-role assignments + __table_args__ = (db.UniqueConstraint("user_id", "role_id", name="_user_role_uc"),) + + +class RolesLookup(db.Model): + __tablename__ = "roles_lookup" + id = db.Column(db.Integer, primary_key=True) + role_name = db.Column(db.String(16), nullable=False) + department_name = db.Column(db.String(64), nullable=False) + + # Establish the many-to-many relationship with users + users = db.relationship("User", secondary="users_roles", back_populates="roles") + + # Unique constraint on role_name and department_name + __table_args__ = ( + db.UniqueConstraint("role_name", "department_name", name="_role_dept_uc"), + ) + + def __repr__(self): + return f"" diff --git a/migrations/versions/d496c141abd6_modded_users_table_and_added_roles_.py b/migrations/versions/d496c141abd6_modded_users_table_and_added_roles_.py new file mode 100644 index 0000000..d289b2b --- /dev/null +++ b/migrations/versions/d496c141abd6_modded_users_table_and_added_roles_.py @@ -0,0 +1,53 @@ +"""Modded users table and added roles tables for many-to-many relationsihps + +Revision ID: d496c141abd6 +Revises: 8e0626ed0ebe +Create Date: 2024-10-15 15:42:30.995773 + +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "d496c141abd6" +down_revision = "8e0626ed0ebe" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table( + "roles_lookup", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("role_name", sa.String(length=16), nullable=False), + sa.Column("department_name", sa.String(length=64), nullable=False), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("role_name", "department_name", name="_role_dept_uc"), + ) + op.create_table( + "users_roles", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("user_id", sa.Integer(), nullable=False), + sa.Column("role_id", sa.Integer(), nullable=False), + sa.ForeignKeyConstraint( + ["role_id"], + ["roles_lookup.id"], + ), + sa.ForeignKeyConstraint( + ["user_id"], + ["users.id"], + ), + sa.PrimaryKeyConstraint("id"), + sa.UniqueConstraint("user_id", "role_id", name="_user_role_uc"), + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table("users_roles") + op.drop_table("roles_lookup") + # ### end Alembic commands ###