-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: support for soft deletion of casbin rules (#72)
* feat: add support for soft deletion of casbin rules * refactor: improve reusability of test case * fix: type hints * test: soft delete * chore: updated .gitignore * refactor: pass the sqlalchemy attribute itself instead of the attribute name string * test: softdelete flag in database * refactor: save_policy - load rules from db before making changes - improved comments * test: save_policy softdelete strategy * fix: formatted code with black * fix: do not create test.db by default * fix: units tests for CI/CD pipeline * docs: added Soft Delete example * fix: make sure softdelete filter is applied * docs: make usage of explicit * docs: moved softdelete logic into base class * docs: improvement * feat: validate the type of db_class_softdelete_attribute * fix: default value of is_deleted flag
- Loading branch information
Showing
6 changed files
with
413 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -102,4 +102,7 @@ venv.bak/ | |
|
||
# mypy | ||
.mypy_cache/ | ||
.idea | ||
.idea | ||
|
||
# vscode settings | ||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
from datetime import datetime, UTC | ||
|
||
import casbin | ||
from casbin_sqlalchemy_adapter import Base, Adapter | ||
from sqlalchemy import false, Column, DateTime, String, Integer, Boolean | ||
from sqlalchemy.engine.default import DefaultExecutionContext | ||
|
||
from some_user_library import get_current_user_id | ||
|
||
|
||
def _deleted_at_default(context: DefaultExecutionContext) -> datetime | None: | ||
current_parameters = context.get_current_parameters() | ||
if current_parameters.get("is_deleted"): | ||
return datetime.now(UTC) | ||
else: | ||
return None | ||
|
||
|
||
def _deleted_by_default(context: DefaultExecutionContext) -> int | None: | ||
current_parameters = context.get_current_parameters() | ||
if current_parameters.get("is_deleted"): | ||
return get_current_user_id() | ||
else: | ||
return None | ||
|
||
|
||
class BaseModel(Base): | ||
__abstract__ = True | ||
|
||
created_at = Column(DateTime, default=lambda: datetime.now(UTC), nullable=False) | ||
updated_at = Column( | ||
DateTime, | ||
default=lambda: datetime.now(UTC), | ||
onupdate=lambda: datetime.now(UTC), | ||
nullable=False, | ||
) | ||
deleted_at = Column( | ||
DateTime, | ||
default=_deleted_at_default, | ||
onupdate=_deleted_at_default, | ||
nullable=True, | ||
) | ||
|
||
created_by = Column(Integer, default=get_current_user_id, nullable=False) | ||
updated_by = Column( | ||
Integer, | ||
default=get_current_user_id, | ||
onupdate=get_current_user_id, | ||
nullable=False, | ||
) | ||
deleted_by = Column( | ||
Integer, | ||
default=_deleted_by_default, | ||
onupdate=_deleted_by_default, | ||
nullable=True, | ||
) | ||
is_deleted = Column( | ||
Boolean, | ||
default=False, | ||
server_default=false(), | ||
index=True, | ||
nullable=False, | ||
) | ||
|
||
|
||
class CasbinSoftDeleteRule(BaseModel): | ||
__tablename__ = "casbin_rule" | ||
|
||
id = Column(Integer, primary_key=True) | ||
ptype = Column(String(255)) | ||
v0 = Column(String(255)) | ||
v1 = Column(String(255)) | ||
v2 = Column(String(255)) | ||
v3 = Column(String(255)) | ||
v4 = Column(String(255)) | ||
v5 = Column(String(255)) | ||
|
||
|
||
engine = your_engine_factory() | ||
# Initialize the Adapter, pass your custom CasbinRule model | ||
# and pass the Boolean field indicating whether a rule is deleted or not | ||
# your model needs to handle the update of fields | ||
# 'updated_by', 'updated_at', 'deleted_by', etc. | ||
adapter = Adapter( | ||
engine, | ||
CasbinSoftDeleteRule, | ||
CasbinSoftDeleteRule.is_deleted, | ||
) | ||
# Create the Enforcer, etc. | ||
e = casbin.Enforcer("path/to/model.conf", adapter) | ||
... |
Oops, something went wrong.