From 5a25b3d369f958448d54f12a90dad79b74bd99df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=83=91=E1=83=94=E1=83=A5=E1=83=90?= Date: Wed, 26 Nov 2025 18:01:03 +0400 Subject: [PATCH] Added superadmin and admin roles and functionalities --- src/__init__.py | 3 ++- src/admin/__init__.py | 1 + src/admin/book.py | 8 ++++++++ src/admin/user.py | 25 +++++++++++++++++++++++++ src/commands.py | 7 ++++++- src/models/user.py | 9 ++++++++- 6 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 src/admin/user.py diff --git a/src/__init__.py b/src/__init__.py index 670ba13..438ddea 100644 --- a/src/__init__.py +++ b/src/__init__.py @@ -2,7 +2,7 @@ from src.config import Config from src.extensions import db, login_manager, migrate -from src.admin import admin, BookView, GenericView +from src.admin import admin, BookView, GenericView, UserView from src.admin.book import SecureModelView from src.commands import init_db_command, populate_db_command from src.models import MediaType, Language, Genre, Book, BookContent, User @@ -43,6 +43,7 @@ def load_user(user_id): admin.init_app(app) + admin.add_view(UserView(User, db.session, name="მომხმარებელი")) admin.add_view(BookView(Book, db.session, name="წიგნები")) admin.add_view(GenericView(MediaType, db.session, name="მედიის ტიპი", category="ფილტრაცია")) admin.add_view(GenericView(Genre, db.session, name="ჟანრი", category="ფილტრაცია")) diff --git a/src/admin/__init__.py b/src/admin/__init__.py index 96d1ed4..920d31b 100644 --- a/src/admin/__init__.py +++ b/src/admin/__init__.py @@ -2,5 +2,6 @@ from src.admin.book import BookView from src.admin.base import SecureIndexView from src.admin.generic import GenericView +from src.admin.user import UserView admin = Admin(index_view=SecureIndexView(), template_mode="bootstrap4", base_template="admin/admin_base.html") \ No newline at end of file diff --git a/src/admin/book.py b/src/admin/book.py index 9fdff48..9cb45ef 100644 --- a/src/admin/book.py +++ b/src/admin/book.py @@ -2,6 +2,7 @@ from flask_admin.contrib.sqla.filters import FilterEqual from flask_admin.form.upload import ImageUploadField, FileUploadField from flask_admin.model.form import InlineFormAdmin +from flask_login import current_user from markupsafe import Markup from wtforms.fields import TextAreaField @@ -81,3 +82,10 @@ def index_view(self): ]) self._refresh_filters_cache() return super(SecureModelView, self).index_view() + + def is_accessible(self): + return current_user.is_authenticated + + @property + def can_delete(self): + return current_user.role == "superadmin" \ No newline at end of file diff --git a/src/admin/user.py b/src/admin/user.py new file mode 100644 index 0000000..fb1c558 --- /dev/null +++ b/src/admin/user.py @@ -0,0 +1,25 @@ +from src.admin.base import SecureModelView +from flask import redirect, url_for +from flask_login import current_user + +from wtforms import PasswordField + +class UserView(SecureModelView): + column_list = ["username", "role"] + form_excluded_columns = ["password"] + + form_extra_fields = { + "password": PasswordField("Password") + } + + form_columns = ["username", "password", "role"] + + def on_model_change(self, form, model, is_created): + if form.password.data: + model.password = form.password.data + + def is_accessible(self): + return current_user.is_authenticated and current_user.role == "superadmin" + + def inaccessible_callback(self, name, **kwargs): + return redirect(url_for('auth.login')) \ No newline at end of file diff --git a/src/commands.py b/src/commands.py index 125f790..2315586 100644 --- a/src/commands.py +++ b/src/commands.py @@ -20,10 +20,15 @@ def init_db_command(): @with_appcontext def populate_db_command(): click.echo("Populating Users") - user1 = User(username="admin", password="admin123") + user1 = User(username="admin", password="admin123", role="admin") user1.password = "admin123" user1.create() + + user1 = User(username="superadmin", password="superadmin123", role="superadmin") + user1.password = "superadmin123" + user1.create() + click.echo("Populating Media types") media_types = ["წიგნები", "პერიოდიკა", "წერილები", "ხელნაწერები", "აუდიო", "ფოტო"] for media in media_types: diff --git a/src/models/user.py b/src/models/user.py index bf5cea2..0c508f1 100644 --- a/src/models/user.py +++ b/src/models/user.py @@ -13,6 +13,7 @@ class User(BaseModel, UserMixin): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String) _password = db.Column(db.String) + role = db.Column(db.String, default="admin") @property def password(self): @@ -23,4 +24,10 @@ def password(self, value): self._password = generate_password_hash(value) def check_password(self, password): - return check_password_hash(self.password, password) \ No newline at end of file + return check_password_hash(self.password, password) + + def is_superadmin(self): + return self.role == "superadmin" + + def is_admin(self): + return self.role in ["admin", "superadmin"] \ No newline at end of file