1
0
Fork 0
mirror of https://codeberg.org/Mo8it/AdvLabDB.git synced 2024-11-08 21:21:06 +00:00
AdvLabDB/advlabdb/customClasses.py

207 lines
6.4 KiB
Python
Raw Normal View History

2021-07-30 12:20:54 +00:00
from flask import flash, redirect, request, url_for
from flask_admin import AdminIndexView, BaseView, expose
from flask_admin.contrib.sqla import ModelView
2021-06-02 21:43:41 +00:00
from flask_security import current_user
from sqlalchemy import and_
2021-07-13 15:22:15 +00:00
2021-07-30 12:20:54 +00:00
from advlabdb.exceptions import DataBaseException, ModelViewException
from advlabdb.models import (
Assistant,
ExperimentMark,
GroupExperiment,
Part,
PartStudent,
SemesterExperiment,
)
from advlabdb.utils import reportBadAttempt, userActiveSemester
def adminViewIsAccessible():
return current_user.has_role("admin")
2021-07-30 00:03:44 +00:00
def assistantViewIsAccessible():
return current_user.has_role("assistant")
2021-07-30 00:03:44 +00:00
class CustomIndexView(AdminIndexView):
2021-07-01 12:02:23 +00:00
def inaccessible_callback(self, name, **kwargs):
# Redirect to login page if user doesn't have access
return redirect(url_for("security.login", next=request.url))
2021-07-30 00:03:44 +00:00
class SecureAdminIndexView(CustomIndexView):
def is_accessible(self):
return adminViewIsAccessible()
@expose()
def index(self):
active_semester_experiment_marks_query = ExperimentMark.query.filter(
ExperimentMark.part_student.has(PartStudent.part.has(Part.semester == userActiveSemester()))
)
number_of_all_experiment_marks = active_semester_experiment_marks_query.count()
number_of_missing_final_experiment_marks = active_semester_experiment_marks_query.filter(
ExperimentMark.final_experiment_mark == None
).count()
return self.render(
"admin_index.html",
number_of_missing_final_experiment_marks=number_of_missing_final_experiment_marks,
number_of_all_experiment_marks=number_of_all_experiment_marks,
)
2021-07-30 00:03:44 +00:00
class SecureAssistantIndexView(CustomIndexView):
def is_accessible(self):
return assistantViewIsAccessible()
@expose()
def index(self):
active_semester_experiment_marks_query = ExperimentMark.query.filter(
ExperimentMark.group_experiment.has(
GroupExperiment.semester_experiment.has(
and_(
SemesterExperiment.semester == userActiveSemester(),
SemesterExperiment.assistants.any(Assistant.user == current_user),
)
)
)
)
number_of_all_experiment_marks = active_semester_experiment_marks_query.count()
number_of_missing_final_experiment_marks = active_semester_experiment_marks_query.filter(
ExperimentMark.final_experiment_mark == None
).count()
return self.render(
"assistant_index.html",
number_of_missing_final_experiment_marks=number_of_missing_final_experiment_marks,
number_of_all_experiment_marks=number_of_all_experiment_marks,
)
2021-07-30 00:03:44 +00:00
class CustomModelView(ModelView):
2021-07-01 11:12:43 +00:00
create_modal = True
edit_modal = True
details_modal = True
queryFilter = None
2021-07-29 22:24:10 +00:00
customCreateModel = None
2021-07-01 12:02:23 +00:00
def inaccessible_callback(self, name, **kwargs):
# Redirect to login page if user doesn't have access
return redirect(url_for("security.login", next=request.url))
def get_query(self):
if self.queryFilter:
return super().get_query().filter(self.queryFilter())
else:
return super().get_query()
def get_count_query(self):
if self.queryFilter:
return super().get_count_query().filter(self.queryFilter())
else:
return super().get_count_query()
2021-07-13 15:22:15 +00:00
def handle_view_exception(self, exc):
if type(exc) in (ModelViewException, DataBaseException):
2021-07-13 15:22:15 +00:00
flash(str(exc), "error")
return True
return super().handle_view_exception(exc)
2021-07-29 22:24:10 +00:00
def create_model(self, form):
if not self.customCreateModel:
return super().create_model(form)
else:
try:
model = self.customCreateModel(form)
self.session.add(model)
self.on_model_change(form, model, True)
self.session.commit()
except Exception as ex:
flash(str(ex), "error")
self.session.rollback()
else:
self.after_model_change(form, model, True)
return model
2021-07-30 00:03:44 +00:00
class SecureAdminModelView(CustomModelView):
2021-11-30 00:36:19 +00:00
can_export = True
can_set_page_size = True
can_create = True
can_edit = True
can_delete = True
column_display_actions = True
2021-07-30 00:03:44 +00:00
list_template = "admin_list.html"
create_template = "admin_create.html"
edit_template = "admin_edit.html"
def is_accessible(self):
return adminViewIsAccessible()
class SecureAssistantModelView(CustomModelView):
2021-11-30 00:36:19 +00:00
can_export = False
can_set_page_size = False
can_create = False
can_edit = False
can_delete = False
column_display_actions = False
2021-07-30 00:03:44 +00:00
list_template = "assistant_list.html"
create_template = "assistant_create.html"
edit_template = "assistant_edit.html"
def is_accessible(self):
return assistantViewIsAccessible()
2021-09-11 18:48:14 +00:00
2021-11-30 00:36:19 +00:00
def queryFilter(self):
"""
A default filter has to be implemented to restrict assistants read/write access.
See on_model_change!
"""
raise ModelViewException("Not implemented!")
def on_model_change(self, form, model, is_created):
"""
This method is NOT ALLOWED TO BE (completely) OVERWRITTEN!
This method uses the filter returned by queryFilter (which has to be implemented!) to prevent assistants
2022-02-13 19:05:29 +00:00
from modifying models not listed on their view by sending a POST request with a different id.
2021-11-30 00:36:19 +00:00
You can extend this method by implementing a custom on_model_change and then calling super().on_model_change within it.
"""
if is_created:
reportBadAttempt("An assistant tried to create a model!")
raise ModelViewException("Assistants can not create models!")
if model not in self.get_query():
reportBadAttempt("An assistant tried to change a model not in his filter!")
raise ModelViewException("Unauthorized action!")
def on_model_delete(self, model):
reportBadAttempt("An assistant tried to delete a model!")
raise ModelViewException("Assistants can not delete models!")
2021-09-11 18:48:14 +00:00
class SecureAdminBaseView(BaseView):
def is_accessible(self):
return adminViewIsAccessible()
2022-02-23 18:37:09 +00:00
class SecureAssistantBaseView(BaseView):
def is_accessible(self):
return assistantViewIsAccessible()