diff --git a/app/__init__.py b/app/__init__.py
index 75e454890367ec299fec9a078e3b9cee21455e9d..be141adb15748a878d8485b38e338c04efebcaeb 100644
--- a/app/__init__.py
+++ b/app/__init__.py
@@ -1,31 +1,32 @@
-from flask import Flask, url_for, redirect, session, g, abort
+from flask import Flask, g, abort, current_app, request
 from config import Config
 from flask_sqlalchemy import SQLAlchemy
 from flask_migrate import Migrate
 from flask_login import LoginManager, current_user
-from flask_security import Security
-from flask_principal import Principal, Permission, RoleNeed, Identity, identity_loaded, identity_changed
+from flask_principal import Principal, Permission, RoleNeed, identity_loaded
 from flask_wtf.csrf import CSRFProtect
 from dotenv import load_dotenv
 from functools import wraps
 import os
 
+# Initialize extensions
+db = SQLAlchemy()
+migrate = Migrate()
+login_manager = LoginManager()
+csrf = CSRFProtect()
+principal = Principal()
+
 def permission_required(permission):
     def decorator(f):
         @wraps(f)
         def decorated_function(*args, **kwargs):
             if not permission.can():
+                current_app.logger.debug(f'Permission denied for {current_user} attempting to access {request.endpoint}.')
                 abort(403)
             return f(*args, **kwargs)
         return decorated_function
     return decorator
 
-db = SQLAlchemy()
-migrate = Migrate()
-login_manager = LoginManager()
-csrf = CSRFProtect()
-
-from app.models import User, Role, RoleUsers
 
 super_admin_permission = Permission(RoleNeed('super-admin'))
 admin_permission = Permission(RoleNeed('admin'))
@@ -51,31 +52,28 @@ def create_app(config_class=Config):
 
     db.init_app(app)
     migrate.init_app(app, db)
-
-    # Use RoleUsers.get_datastore() instead of RoleUsers.user_datastore
-    security = Security(app, RoleUsers.get_datastore())
-    principal = Principal(app)
+    login_manager.init_app(app)
+    csrf.init_app(app)
+    principal.init_app(app)
 
     # Register blueprints and URL prefixes
     register_blueprints(app)
 
-    # Protect internal endpoints from external use
-    csrf.init_app(app)
-
-    # Identity loader
-    @identity_loaded.connect_via(app)
-    # Identity loader
     @identity_loaded.connect_via(app)
     def on_identity_loaded(sender, identity):
         identity.user = current_user
         if current_user.is_authenticated:
+            from app.models import User
             identity.provides.add(RoleNeed('user'))
-            for role in current_user.roles:
-                identity.provides.add(RoleNeed(role.name))
-                # Should only be allocated to the root account, used for changing users to user -> admin
-                if role.name == 'super-admin':
+            user = User.query.get(current_user.id)
+            if user and user.role:
+                identity.provides.add(RoleNeed(user.role.name))
+                if user.role.name == 'super-admin':
                     identity.provides.add(RoleNeed('admin'))
-                    identity.provides.add(RoleNeed('user'))
+                    identity.provides.add(RoleNeed('super-admin'))
+            else:
+                current_app.logger.debug(f'No role found for user {identity.user.username}.')
+
 
 
     # Add global template variables
@@ -102,29 +100,32 @@ def create_app(config_class=Config):
                 'super_admin_permission': g.super_admin_permission
             }
 
-
-    @app.errorhandler(Exception)
-    def handle_exception(e):
-        app.logger.error(f"Unhandled exception: {e}")
-        session['error_message'] = str(e)
-        return redirect(url_for('errors.quandary'))
-
     @app.before_request
     def before_request():
         g.admin_permission = admin_permission
         g.user_permission = user_permission
         g.super_admin_permission = super_admin_permission
-        if current_user.is_authenticated:
-            identity_changed.send(current_user._get_current_object(), identity=Identity(current_user.id))
 
+        if current_user.is_authenticated:
+            role = current_user.role
+            if role:
+                if role.name == 'super-admin':
+                    g.super_admin_permission = super_admin_permission
+                    g.admin_permission = admin_permission
+                    g.user_permission = user_permission
+                elif role.name == 'admin':
+                    g.admin_permission = admin_permission
+                    g.user_permission = user_permission
+                elif role.name == 'user':
+                    g.user_permission = user_permission
 
     login_manager.login_view = 'profile.login'
-    login_manager.init_app(app)
-
+    
     return app
 
 @login_manager.user_loader
 def load_user(user_id):
+    from app.models import User
     return User.query.get(int(user_id))
 
 def register_blueprints(app):
@@ -139,3 +140,10 @@ def register_blueprints(app):
     for module_name, url_prefix in blueprints:
         module = __import__(f'app.{module_name}', fromlist=['bp'])
         app.register_blueprint(module.bp, url_prefix=url_prefix)
+
+# @app.errorhandler(Exception)
+    # def handle_exception(e):
+    #     app.logger.error(f"Unhandled exception: {e}")
+    #     session['error_message'] = str(e)
+    #     return redirect(url_for('errors.quandary'))
+    #     pass
\ No newline at end of file
diff --git a/app/bookings/routes.py b/app/bookings/routes.py
index 92779b487c4793013914a6293a9c20450040a932..a340d57c28ec9dbaa3123c56e492c06a351540c4 100644
--- a/app/bookings/routes.py
+++ b/app/bookings/routes.py
@@ -1,10 +1,10 @@
 from flask import render_template, redirect, url_for, g
 from app.bookings import bp
 from app.models import Listings, ListingImages 
-from app import admin_permission, permission_required
+from app import admin_permission, permission_required, user_permission, super_admin_permission
 
 @bp.route('/home')
-@permission_required(admin_permission)
+@permission_required(user_permission)
 def index():
     listing_ids = []
     top_listings = Listings.get_top_listings(5)
diff --git a/app/models/__init__.py b/app/models/__init__.py
index 0e4cd79972ae43b67102256add861bf191b4760a..de002ee550559f9e3ab304de74c795b7e9718841 100644
--- a/app/models/__init__.py
+++ b/app/models/__init__.py
@@ -2,5 +2,4 @@
 from .user import User
 from .listings import Listings
 from .listing_images import ListingImages 
-from .role import Role
-from .role_users import RoleUsers
\ No newline at end of file
+from .role import Role
\ No newline at end of file
diff --git a/app/models/role_users.py b/app/models/role_users.py
deleted file mode 100644
index ed3275773405771c621149c587555d6cb8cf8862..0000000000000000000000000000000000000000
--- a/app/models/role_users.py
+++ /dev/null
@@ -1,22 +0,0 @@
-from flask_security import SQLAlchemyUserDatastore
-from app import db
-
-class RoleUsers:
-    roles_users = db.Table('roles_users',
-        db.Column('user_id', db.Integer(), db.ForeignKey('users.id'), primary_key=True, index=True),
-        db.Column('role_id', db.Integer(), db.ForeignKey('roles.id'))
-    )
-
-    @staticmethod
-    def get_datastore():
-        from app.models.role import Role
-        from app.models.user import User
-        return SQLAlchemyUserDatastore(db, User, Role)
-
-    @staticmethod
-    def add_role_to_user(user, role_name):
-        from app.models.role import Role
-        role = Role.query.filter_by(name=role_name).first()
-        if role and role not in user.roles:
-            user.roles.append(role)
-            db.session.commit()
diff --git a/app/models/user.py b/app/models/user.py
index 5fd1487a59c7beb4b6a4d056dcd768eb3fe3c3c3..c0b838ad0893f17f0ce3f45d8345165c74da3d23 100644
--- a/app/models/user.py
+++ b/app/models/user.py
@@ -1,9 +1,7 @@
-from flask import request, jsonify
 from flask_login import UserMixin
-from werkzeug.security import generate_password_hash, check_password_hash
+from werkzeug.security import generate_password_hash
 from app import db
 import os
-# Avoid importing Role and RoleUsers here to prevent circular import
 
 class User(UserMixin, db.Model):
     __tablename__ = 'users'
@@ -12,12 +10,10 @@ class User(UserMixin, db.Model):
     username = db.Column(db.String(255), nullable=False, unique=True)
     email = db.Column(db.String(255), nullable=False, unique=True)
     password = db.Column(db.String(255), nullable=False)
-    fs_uniquifier = db.Column(db.String(64), unique=True, nullable=False)  # Add fs_uniquifier field
+    fs_uniquifier = db.Column(db.String(64), unique=True, nullable=False)
 
-    # Import Role and RoleUsers only when defining the roles relationship
-    from app.models.role_users import RoleUsers
-    from app.models.role import Role
-    roles = db.relationship('Role', secondary=RoleUsers.roles_users, backref=db.backref('users', lazy='dynamic'))
+    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
+    role = db.relationship('Role', backref=db.backref('users', lazy=True))
 
     @classmethod
     def create_user(cls, username, email, password, role_name='user'):
@@ -27,32 +23,36 @@ class User(UserMixin, db.Model):
     
         role = Role.query.filter_by(name=role_name).first()
         if role:
-            new_user.roles.append(role)
+            new_user.role = role
         db.session.add(new_user)
         db.session.commit()
 
         return new_user
 
-
     @classmethod
     def search_user_id(cls, user_id):
         return cls.query.get(user_id)
-    
+
     @classmethod
     def search_user_by_email(cls, user_email):
-        email_exist = cls.query.filter_by(email=user_email).first()
-        
-        return email_exist
+        return cls.query.filter_by(email=user_email).first()
     
     @classmethod
     def search_user_by_username(cls, user_name):
-        user_exist = cls.query.filter_by(username=user_name).first()
-        
-        return user_exist
+        return cls.query.filter_by(username=user_name).first()
     
     @classmethod
     def change_user_password(cls, email, password):
         user = cls.search_user_by_email(email)
-
         if user is None:
             raise ValueError("Error")
+        hashed_password = generate_password_hash(password, method='pbkdf2:sha256')
+        user.password = hashed_password
+        db.session.commit()
+
+    @classmethod
+    def get_user_role(cls, user_id):
+        user = cls.query.get(user_id)
+        if user and user.role:
+            return user.role.name
+        return None
diff --git a/app/profile/routes.py b/app/profile/routes.py
index bd6df0448ca7d4e4b62d97fbe356170351b622b9..4b04a1a61371fd4021608044ad02da8801ab7bec 100644
--- a/app/profile/routes.py
+++ b/app/profile/routes.py
@@ -1,11 +1,13 @@
 #https://www.digitalocean.com/community/tutorials/how-to-add-authentication-to-your-app-with-flask-login#step-1-installing-packages
-from flask import render_template, redirect, url_for, request, flash, jsonify, session
-from app.profile import bp
+from flask import render_template, redirect, url_for, request, flash, jsonify, session, current_app
+from flask_principal import Identity, identity_changed
+from flask_login import login_user, logout_user, login_required, current_user
 from werkzeug.security import check_password_hash
+from app.profile import bp
 from app.models import User
-from app import db
-from flask_login import login_user, logout_user, login_required, current_user
 from app.logger import auth_logger
+from app import db
+
 
 @bp.route('/signup', methods=['GET', 'POST'])
 def signup():
@@ -61,6 +63,8 @@ def is_valid_username(username):
     return all(c.isalnum() or c in allowed_special_chars for c in username)
 
 
+from flask_principal import Identity, identity_changed
+
 @bp.route('/login', methods=['POST'])
 def login_post():
     username_field = request.form.get('username')
@@ -77,9 +81,13 @@ def login_post():
         return redirect(url_for('profile.login', error=True))
 
     login_user(user, remember=remember)
+
+    identity_changed.send(current_app._get_current_object(), identity=Identity(user.id))
+
     return redirect(url_for('profile.index'))
 
 
+
 @bp.route('/check-username', methods=['POST'])
 def check_username():
     data = request.get_json()
diff --git a/migrations/versions/6c7070736062_add_role_id_to_users_table.py b/migrations/versions/6c7070736062_add_role_id_to_users_table.py
new file mode 100644
index 0000000000000000000000000000000000000000..06ca58762200695b2506fcaba3b348e875d99077
--- /dev/null
+++ b/migrations/versions/6c7070736062_add_role_id_to_users_table.py
@@ -0,0 +1,26 @@
+"""Add role_id to users table
+
+Revision ID: 6c7070736062
+Revises: ad8ca3c3dfaa
+Create Date: 2025-01-06 20:16:19.191868
+
+"""
+from alembic import op
+import sqlalchemy as sa
+from sqlalchemy.dialects import mysql
+
+# revision identifiers, used by Alembic.
+revision = '6c7070736062'
+down_revision = 'ad8ca3c3dfaa'
+branch_labels = None
+depends_on = None
+
+def upgrade():
+    # Add column role_id to users table
+    op.add_column('users', sa.Column('role_id', sa.Integer(), nullable=True))
+    op.create_foreign_key(None, 'users', 'roles', ['role_id'], ['id'])
+
+def downgrade():
+    # Remove column role_id from users table
+    op.drop_constraint(None, 'users', type_='foreignkey')
+    op.drop_column('users', 'role_id')
diff --git a/migrations/versions/ac9d4555724d_add_api_token_and_expiry.py b/migrations/versions/ac9d4555724d_add_api_token_and_expiry.py
index e93fdc531d938284d03cd0cd797f28dfed8b5ce9..59f4c9a590293c9ba96b7d83bef1228cdce3a182 100644
--- a/migrations/versions/ac9d4555724d_add_api_token_and_expiry.py
+++ b/migrations/versions/ac9d4555724d_add_api_token_and_expiry.py
@@ -23,7 +23,5 @@ def upgrade():
               sa.Column('username', sa.String(255), nullable=False, unique=True),
               sa.Column('email', sa.String(255), nullable=False, unique=True),
               sa.Column('password', sa.String(255), nullable=False),
-              sa.Column('role_id', sa.SmallInteger(), nullable=False, server_default='1'), #Standard user permission level
-              sa.Column('api_token', sa.String(255), nullable=True, unique=True),
-              sa.Column('token_expiry', sa.DateTime(), nullable=True)
+              sa.Column('role_id', sa.SmallInteger(), nullable=False, server_default='3')
        )
\ No newline at end of file
diff --git a/migrations/versions/ad8ca3c3dfaa_add_composite_primary_key_and_index_to_.py b/migrations/versions/ad8ca3c3dfaa_add_composite_primary_key_and_index_to_.py
deleted file mode 100644
index 6ffcbf94f8f82a0daec75b7331366ac24c3f77c6..0000000000000000000000000000000000000000
--- a/migrations/versions/ad8ca3c3dfaa_add_composite_primary_key_and_index_to_.py
+++ /dev/null
@@ -1,35 +0,0 @@
-"""Add composite primary key and index to roles_users
-
-Revision ID: ad8ca3c3dfaa
-Revises: 22de5b143d05
-Create Date: 2025-01-06 13:56:13.747100
-
-"""
-from alembic import op
-import sqlalchemy as sa
-
-
-# revision identifiers, used by Alembic.
-revision = 'ad8ca3c3dfaa'
-down_revision = '22de5b143d05'
-branch_labels = None
-depends_on = None
-
-
-def upgrade():
-    op.drop_table('roles_users')
-    
-    op.create_table(
-        'roles_users',
-        sa.Column('user_id', sa.Integer, sa.ForeignKey('users.id'), primary_key=True, index=True),
-        sa.Column('role_id', sa.Integer, sa.ForeignKey('roles.id'), primary_key=True)
-    )
-
-def downgrade():
-    op.drop_table('roles_users')
-    
-    op.create_table(
-        'roles_users',
-        sa.Column('user_id', sa.Integer, sa.ForeignKey('users.id')),
-        sa.Column('role_id', sa.Integer, sa.ForeignKey('roles.id'))
-    )