2023-10-26 20:38:31 +00:00
|
|
|
from base.orm import Base, local_session, REGISTRY
|
2023-10-26 17:56:42 +00:00
|
|
|
from sqlalchemy import Column, ForeignKey, String, TypeDecorator, UniqueConstraint
|
2022-07-21 11:58:50 +00:00
|
|
|
from sqlalchemy.orm import relationship
|
2022-09-17 18:12:14 +00:00
|
|
|
|
2023-10-26 20:38:31 +00:00
|
|
|
import warnings
|
2021-06-28 09:08:09 +00:00
|
|
|
|
2022-11-24 08:27:01 +00:00
|
|
|
# Role Based Access Control #
|
|
|
|
|
2023-01-31 07:30:21 +00:00
|
|
|
|
2021-08-20 09:27:19 +00:00
|
|
|
class ClassType(TypeDecorator):
|
2022-09-03 10:50:14 +00:00
|
|
|
impl = String
|
2021-06-28 09:08:09 +00:00
|
|
|
|
2022-09-03 10:50:14 +00:00
|
|
|
@property
|
|
|
|
def python_type(self):
|
|
|
|
return NotImplemented
|
2021-06-28 09:08:09 +00:00
|
|
|
|
2022-09-03 10:50:14 +00:00
|
|
|
def process_literal_param(self, value, dialect):
|
|
|
|
return NotImplemented
|
2021-06-28 09:08:09 +00:00
|
|
|
|
2022-09-03 10:50:14 +00:00
|
|
|
def process_bind_param(self, value, dialect):
|
|
|
|
return value.__name__ if isinstance(value, type) else str(value)
|
2021-06-28 09:08:09 +00:00
|
|
|
|
2022-09-03 10:50:14 +00:00
|
|
|
def process_result_value(self, value, dialect):
|
|
|
|
class_ = REGISTRY.get(value)
|
|
|
|
if class_ is None:
|
|
|
|
warnings.warn(f"Can't find class <{value}>,find it yourself!", stacklevel=2)
|
|
|
|
return class_
|
2021-06-28 09:08:09 +00:00
|
|
|
|
|
|
|
|
2022-09-03 10:50:14 +00:00
|
|
|
class Role(Base):
|
|
|
|
__tablename__ = "role"
|
|
|
|
|
|
|
|
name = Column(String, nullable=False, comment="Role Name")
|
|
|
|
desc = Column(String, nullable=True, comment="Role Description")
|
|
|
|
community = Column(
|
|
|
|
ForeignKey("community.id", ondelete="CASCADE"),
|
|
|
|
nullable=False,
|
|
|
|
comment="Community",
|
|
|
|
)
|
|
|
|
permissions = relationship(lambda: Permission)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def init_table():
|
|
|
|
with local_session() as session:
|
2022-11-24 08:27:01 +00:00
|
|
|
r = session.query(Role).filter(Role.name == "author").first()
|
|
|
|
if r:
|
|
|
|
Role.default_role = r
|
|
|
|
return
|
2022-09-03 10:50:14 +00:00
|
|
|
|
2022-11-24 08:27:01 +00:00
|
|
|
r1 = Role.create(
|
2022-09-03 10:50:14 +00:00
|
|
|
name="author",
|
2022-11-24 08:27:01 +00:00
|
|
|
desc="Role for an author",
|
|
|
|
community=1,
|
|
|
|
)
|
|
|
|
|
|
|
|
session.add(r1)
|
|
|
|
|
|
|
|
Role.default_role = r1
|
|
|
|
|
|
|
|
r2 = Role.create(
|
|
|
|
name="reader",
|
|
|
|
desc="Role for a reader",
|
|
|
|
community=1,
|
|
|
|
)
|
|
|
|
|
|
|
|
session.add(r2)
|
|
|
|
|
|
|
|
r3 = Role.create(
|
|
|
|
name="expert",
|
|
|
|
desc="Role for an expert",
|
|
|
|
community=1,
|
|
|
|
)
|
|
|
|
|
|
|
|
session.add(r3)
|
|
|
|
|
|
|
|
r4 = Role.create(
|
|
|
|
name="editor",
|
|
|
|
desc="Role for an editor",
|
2022-11-19 11:35:34 +00:00
|
|
|
community=1,
|
2022-09-03 10:50:14 +00:00
|
|
|
)
|
|
|
|
|
2022-11-24 08:27:01 +00:00
|
|
|
session.add(r4)
|
2021-12-08 12:51:30 +00:00
|
|
|
|
|
|
|
|
2021-06-28 09:08:09 +00:00
|
|
|
class Operation(Base):
|
2022-09-03 10:50:14 +00:00
|
|
|
__tablename__ = "operation"
|
|
|
|
name = Column(String, nullable=False, unique=True, comment="Operation Name")
|
2021-08-17 09:14:26 +00:00
|
|
|
|
2022-09-03 10:50:14 +00:00
|
|
|
@staticmethod
|
|
|
|
def init_table():
|
|
|
|
with local_session() as session:
|
2022-11-24 08:27:01 +00:00
|
|
|
for name in ["create", "update", "delete", "load"]:
|
|
|
|
"""
|
|
|
|
* everyone can:
|
|
|
|
- load shouts
|
|
|
|
- load topics
|
|
|
|
- load reactions
|
|
|
|
- create an account to become a READER
|
|
|
|
* readers can:
|
|
|
|
- update and delete their account
|
|
|
|
- load chats
|
|
|
|
- load messages
|
|
|
|
- create reaction of some shout's author allowed kinds
|
|
|
|
- create shout to become an AUTHOR
|
|
|
|
* authors can:
|
|
|
|
- update and delete their shout
|
|
|
|
- invite other authors to edit shout and chat
|
|
|
|
- manage allowed reactions for their shout
|
|
|
|
* pros can:
|
|
|
|
- create/update/delete their community
|
|
|
|
- create/update/delete topics for their community
|
|
|
|
|
|
|
|
"""
|
|
|
|
op = session.query(Operation).filter(Operation.name == name).first()
|
|
|
|
if not op:
|
|
|
|
op = Operation.create(name=name)
|
|
|
|
session.add(op)
|
|
|
|
session.commit()
|
2021-06-28 09:08:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Resource(Base):
|
2022-09-03 10:50:14 +00:00
|
|
|
__tablename__ = "resource"
|
2023-10-26 17:56:42 +00:00
|
|
|
resourceClass = Column(String, nullable=False, unique=True, comment="Resource class")
|
2022-09-03 10:50:14 +00:00
|
|
|
name = Column(String, nullable=False, unique=True, comment="Resource name")
|
2022-11-24 08:27:01 +00:00
|
|
|
# TODO: community = Column(ForeignKey())
|
2021-08-17 09:14:26 +00:00
|
|
|
|
2022-09-03 10:50:14 +00:00
|
|
|
@staticmethod
|
|
|
|
def init_table():
|
|
|
|
with local_session() as session:
|
2023-10-26 17:56:42 +00:00
|
|
|
for res in [
|
|
|
|
"shout",
|
|
|
|
"topic",
|
|
|
|
"reaction",
|
|
|
|
"chat",
|
|
|
|
"message",
|
|
|
|
"invite",
|
|
|
|
"community",
|
|
|
|
"user",
|
|
|
|
]:
|
2022-11-24 08:27:01 +00:00
|
|
|
r = session.query(Resource).filter(Resource.name == res).first()
|
|
|
|
if not r:
|
2022-11-29 19:13:03 +00:00
|
|
|
r = Resource.create(name=res, resourceClass=res)
|
2022-11-24 08:27:01 +00:00
|
|
|
session.add(r)
|
|
|
|
session.commit()
|
2021-06-28 09:08:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Permission(Base):
|
2022-09-03 10:50:14 +00:00
|
|
|
__tablename__ = "permission"
|
|
|
|
__table_args__ = (
|
2022-11-30 17:21:15 +00:00
|
|
|
UniqueConstraint("role", "operation", "resource"),
|
2022-09-03 10:50:14 +00:00
|
|
|
{"extend_existing": True},
|
|
|
|
)
|
|
|
|
|
2023-10-26 17:56:42 +00:00
|
|
|
role = Column(ForeignKey("role.id", ondelete="CASCADE"), nullable=False, comment="Role")
|
2022-11-30 17:21:15 +00:00
|
|
|
operation = Column(
|
2022-09-03 10:50:14 +00:00
|
|
|
ForeignKey("operation.id", ondelete="CASCADE"),
|
|
|
|
nullable=False,
|
|
|
|
comment="Operation",
|
|
|
|
)
|
2022-11-30 17:21:15 +00:00
|
|
|
resource = Column(
|
2022-09-03 10:50:14 +00:00
|
|
|
ForeignKey("resource.id", ondelete="CASCADE"),
|
|
|
|
nullable=False,
|
|
|
|
comment="Resource",
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2023-10-26 20:38:31 +00:00
|
|
|
# if __name__ == "__main__":
|
|
|
|
# Base.metadata.create_all(engine)
|
|
|
|
# ops = [
|
|
|
|
# Permission(role=1, operation=1, resource=1),
|
|
|
|
# Permission(role=1, operation=2, resource=1),
|
|
|
|
# Permission(role=1, operation=3, resource=1),
|
|
|
|
# Permission(role=1, operation=4, resource=1),
|
|
|
|
# Permission(role=2, operation=4, resource=1),
|
|
|
|
# ]
|
|
|
|
# global_session.add_all(ops)
|
|
|
|
# global_session.commit()
|