shaapi 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. shaapi/__init__.py +3 -0
  2. shaapi/cli.py +97 -0
  3. shaapi/generator.py +114 -0
  4. shaapi/template/.dockerignore +37 -0
  5. shaapi/template/.env.template +59 -0
  6. shaapi/template/.gitattributes +12 -0
  7. shaapi/template/.gitignore +170 -0
  8. shaapi/template/.gitlab-ci.yml +89 -0
  9. shaapi/template/Dockerfile +59 -0
  10. shaapi/template/LICENSE +21 -0
  11. shaapi/template/README.md +206 -0
  12. shaapi/template/backend/.gitignore +164 -0
  13. shaapi/template/backend/__init__.py +0 -0
  14. shaapi/template/backend/alembic/README +1 -0
  15. shaapi/template/backend/alembic/env.py +102 -0
  16. shaapi/template/backend/alembic/script.py.mako +26 -0
  17. shaapi/template/backend/alembic/versions/2026_06_08_1024-64524c63b666_initial.py +143 -0
  18. shaapi/template/backend/alembic.ini +117 -0
  19. shaapi/template/backend/app/__init__.py +55 -0
  20. shaapi/template/backend/app/admin/__init__.py +1 -0
  21. shaapi/template/backend/app/admin/api/v1/__init__.py +0 -0
  22. shaapi/template/backend/app/admin/api/v1/auth.py +59 -0
  23. shaapi/template/backend/app/admin/api/v1/casbin.py +218 -0
  24. shaapi/template/backend/app/admin/api/v1/login_log.py +63 -0
  25. shaapi/template/backend/app/admin/api/v1/opera_log.py +61 -0
  26. shaapi/template/backend/app/admin/api/v1/role.py +108 -0
  27. shaapi/template/backend/app/admin/api/v1/user.py +47 -0
  28. shaapi/template/backend/app/admin/schema/casbin_rule.py +45 -0
  29. shaapi/template/backend/app/admin/schema/login_log.py +36 -0
  30. shaapi/template/backend/app/admin/schema/opera_log.py +43 -0
  31. shaapi/template/backend/app/admin/schema/role.py +36 -0
  32. shaapi/template/backend/app/admin/schema/sso.py +37 -0
  33. shaapi/template/backend/app/admin/schema/token.py +74 -0
  34. shaapi/template/backend/app/admin/schema/user.py +93 -0
  35. shaapi/template/backend/app/admin/service/auth_service.py +233 -0
  36. shaapi/template/backend/app/admin/service/casbin_service.py +135 -0
  37. shaapi/template/backend/app/admin/service/login_log_service.py +62 -0
  38. shaapi/template/backend/app/admin/service/opera_log_service.py +31 -0
  39. shaapi/template/backend/app/admin/service/role_service.py +79 -0
  40. shaapi/template/backend/app/admin/service/secure_token_service.py +60 -0
  41. shaapi/template/backend/app/admin/service/user_service.py +153 -0
  42. shaapi/template/backend/app/api.py +11 -0
  43. shaapi/template/backend/common/__init__.py +0 -0
  44. shaapi/template/backend/common/cloud_storage/__init__.py +11 -0
  45. shaapi/template/backend/common/cloud_storage/cloud_storage.py +180 -0
  46. shaapi/template/backend/common/dataclasses.py +52 -0
  47. shaapi/template/backend/common/email_conf/email.py +105 -0
  48. shaapi/template/backend/common/enums.py +144 -0
  49. shaapi/template/backend/common/exception/__init__.py +0 -0
  50. shaapi/template/backend/common/exception/errors.py +87 -0
  51. shaapi/template/backend/common/exception/exception_handler.py +280 -0
  52. shaapi/template/backend/common/log.py +123 -0
  53. shaapi/template/backend/common/model.py +68 -0
  54. shaapi/template/backend/common/pagination.py +83 -0
  55. shaapi/template/backend/common/response/__init__.py +0 -0
  56. shaapi/template/backend/common/response/response_code.py +158 -0
  57. shaapi/template/backend/common/response/response_schema.py +110 -0
  58. shaapi/template/backend/common/schema.py +144 -0
  59. shaapi/template/backend/common/security/jwt.py +203 -0
  60. shaapi/template/backend/common/security/rbac.py +98 -0
  61. shaapi/template/backend/common/security/sec_token.py +6 -0
  62. shaapi/template/backend/common/socketio/action.py +11 -0
  63. shaapi/template/backend/common/socketio/server.py +50 -0
  64. shaapi/template/backend/common/sso/base.py +69 -0
  65. shaapi/template/backend/common/sso/google.py +127 -0
  66. shaapi/template/backend/core/conf.py +208 -0
  67. shaapi/template/backend/core/path_conf.py +24 -0
  68. shaapi/template/backend/core/registrar.py +195 -0
  69. shaapi/template/backend/crud/__init__.py +1 -0
  70. shaapi/template/backend/crud/crud_base.py +35 -0
  71. shaapi/template/backend/crud/crud_casbin.py +46 -0
  72. shaapi/template/backend/crud/crud_login_log.py +58 -0
  73. shaapi/template/backend/crud/crud_opera_log.py +58 -0
  74. shaapi/template/backend/crud/crud_role.py +128 -0
  75. shaapi/template/backend/crud/crud_user.py +267 -0
  76. shaapi/template/backend/database/__init__.py +0 -0
  77. shaapi/template/backend/database/db_postgres.py +125 -0
  78. shaapi/template/backend/database/db_redis.py +62 -0
  79. shaapi/template/backend/entrypoint-api.sh +19 -0
  80. shaapi/template/backend/lang/en/app.py +18 -0
  81. shaapi/template/backend/lang/en/auth.py +10 -0
  82. shaapi/template/backend/lang/fr/app.py +18 -0
  83. shaapi/template/backend/lang/fr/auth.py +10 -0
  84. shaapi/template/backend/main.py +54 -0
  85. shaapi/template/backend/middleware/__init__.py +1 -0
  86. shaapi/template/backend/middleware/access_middleware.py +19 -0
  87. shaapi/template/backend/middleware/i18n_middleware.py +19 -0
  88. shaapi/template/backend/middleware/jwt_auth_middleware.py +73 -0
  89. shaapi/template/backend/middleware/opera_log_middleware.py +179 -0
  90. shaapi/template/backend/middleware/state_middleware.py +26 -0
  91. shaapi/template/backend/models/__init__.py +10 -0
  92. shaapi/template/backend/models/associations.py +20 -0
  93. shaapi/template/backend/models/casbin_rule.py +30 -0
  94. shaapi/template/backend/models/login_log.py +28 -0
  95. shaapi/template/backend/models/opera_log.py +36 -0
  96. shaapi/template/backend/models/role.py +27 -0
  97. shaapi/template/backend/models/user.py +30 -0
  98. shaapi/template/backend/seeder/json/admin.json +15 -0
  99. shaapi/template/backend/seeder/json/user.json +15 -0
  100. shaapi/template/backend/seeder/run.py +34 -0
  101. shaapi/template/backend/static/ip2region.xdb +0 -0
  102. shaapi/template/backend/templates/build/meet.html +169 -0
  103. shaapi/template/backend/templates/build/new_account.html +373 -0
  104. shaapi/template/backend/templates/build/reset-password.html +170 -0
  105. shaapi/template/backend/templates/build/test_email.html +25 -0
  106. shaapi/template/backend/templates/build/welcome-one-1.html +160 -0
  107. shaapi/template/backend/templates/build/welcome-one.html +178 -0
  108. shaapi/template/backend/templates/build/welcome-two.html +234 -0
  109. shaapi/template/backend/templates/index.html +0 -0
  110. shaapi/template/backend/templates/src/new_account.mjml +15 -0
  111. shaapi/template/backend/templates/src/reset_password.mjml +19 -0
  112. shaapi/template/backend/templates/src/test_email.mjml +11 -0
  113. shaapi/template/backend/templates/ws/ws.html +70 -0
  114. shaapi/template/backend/utils/demo_site.py +18 -0
  115. shaapi/template/backend/utils/encrypt.py +108 -0
  116. shaapi/template/backend/utils/health_check.py +34 -0
  117. shaapi/template/backend/utils/prometheus.py +135 -0
  118. shaapi/template/backend/utils/request_parse.py +110 -0
  119. shaapi/template/backend/utils/serializers.py +75 -0
  120. shaapi/template/backend/utils/timezone.py +51 -0
  121. shaapi/template/backend/utils/trace_id.py +7 -0
  122. shaapi/template/backend/utils/translator.py +28 -0
  123. shaapi/template/devops/scripts/deploy.sh +7 -0
  124. shaapi/template/devops/scripts/setup_env.sh +62 -0
  125. shaapi/template/docker-compose.monitoring.yml +63 -0
  126. shaapi/template/docker-compose.override.yml +12 -0
  127. shaapi/template/docker-compose.yml +90 -0
  128. shaapi/template/docker-run.sh +99 -0
  129. shaapi/template/etc/dashboards/fastapi-observability.json +1044 -0
  130. shaapi/template/etc/dashboards.yaml +10 -0
  131. shaapi/template/etc/grafana/datasource.yml +79 -0
  132. shaapi/template/etc/prometheus/prometheus.yml +52 -0
  133. shaapi/template/package-lock.json +2102 -0
  134. shaapi/template/package.json +16 -0
  135. shaapi/template/pyproject.toml +78 -0
  136. shaapi/template/uv.lock +2866 -0
  137. shaapi-0.1.0.dist-info/METADATA +92 -0
  138. shaapi-0.1.0.dist-info/RECORD +141 -0
  139. shaapi-0.1.0.dist-info/WHEEL +4 -0
  140. shaapi-0.1.0.dist-info/entry_points.txt +2 -0
  141. shaapi-0.1.0.dist-info/licenses/LICENCE +21 -0
@@ -0,0 +1,195 @@
1
+ from contextlib import asynccontextmanager
2
+
3
+ from asgi_correlation_id import CorrelationIdMiddleware
4
+ from fastapi import Depends, FastAPI, APIRouter
5
+ from fastapi_limiter import FastAPILimiter
6
+ from fastapi_pagination import add_pagination
7
+ from starlette.middleware.authentication import AuthenticationMiddleware
8
+
9
+ from backend.common.exception.exception_handler import register_exception
10
+ from backend.common.log import set_customize_logfile, setup_logging
11
+ from backend.core.conf import settings
12
+ from backend.core.path_conf import STATIC_DIR
13
+ from backend.database.db_postgres import create_table
14
+ from backend.database.db_redis import redis_client
15
+ from backend.middleware.jwt_auth_middleware import JwtAuthMiddleware
16
+ from backend.middleware.opera_log_middleware import OperaLogMiddleware
17
+ from backend.middleware.state_middleware import StateMiddleware
18
+ from backend.middleware.i18n_middleware import I18nMiddleware
19
+ from backend.utils.demo_site import demo_site
20
+ from backend.utils.health_check import ensure_unique_route_names, http_limit_callback
21
+ from backend.utils.serializers import MsgSpecJSONResponse
22
+
23
+
24
+
25
+
26
+ @asynccontextmanager
27
+ async def register_init(app: FastAPI):
28
+ """
29
+ Start initialization
30
+
31
+ :return:
32
+ """
33
+ # Creating database tables (dev convenience). In production rely on Alembic
34
+ # migrations and set DB_AUTO_CREATE=false.
35
+ if settings.DB_AUTO_CREATE:
36
+ await create_table()
37
+ # Connecting to redis
38
+ await redis_client.open()
39
+ # Initialize limiter
40
+ await FastAPILimiter.init(
41
+ redis=redis_client,
42
+ prefix=settings.REQUEST_LIMITER_REDIS_PREFIX,
43
+ http_callback=http_limit_callback,
44
+ )
45
+
46
+ yield
47
+
48
+ # Closing a redis connection
49
+ await redis_client.close()
50
+ # Close limiter
51
+ await FastAPILimiter.close()
52
+
53
+
54
+ def register_app(router: APIRouter, name: str = "Parse name" ) -> FastAPI:
55
+ # FastAPI
56
+ app = FastAPI(
57
+ title=f"[{settings.ENVIRONMENT.upper()}] {settings.FASTAPI_TITLE} {name.upper()}",
58
+ contact={
59
+ "name": "shaapi",
60
+ "email": "shalomtehe219@gmail.com",
61
+ },
62
+ version=settings.FASTAPI_VERSION,
63
+ description=settings.FASTAPI_DESCRIPTION,
64
+ docs_url=f"{settings.FASTAPI_DOCS_URL}",
65
+ redoc_url=f"{settings.FASTAPI_REDOCS_URL}",
66
+ openapi_url=f"{settings.FASTAPI_OPENAPI_URL}",
67
+ default_response_class=MsgSpecJSONResponse,
68
+ # NOTE: the lifespan is owned by the parent app (see backend/main.py).
69
+ # Starlette does NOT run the lifespan of mounted sub-applications, so
70
+ # shared resources (DB tables, Redis, rate limiter) are initialized once
71
+ # on the parent instead.
72
+ )
73
+
74
+ # log (computing)
75
+ register_logger()
76
+
77
+ # Static files
78
+ register_static_file(app)
79
+
80
+ # middleware
81
+ register_middleware(app, name)
82
+
83
+ # routing (in computer networks)
84
+ register_router(app, router)
85
+
86
+ # tab window (in a web browser etc)
87
+ register_page(app)
88
+
89
+ # Global Exception Handling
90
+ register_exception(app)
91
+ return app
92
+
93
+
94
+ def register_logger() -> None:
95
+ """
96
+ System Log
97
+
98
+ :return:
99
+ """
100
+ setup_logging()
101
+ set_customize_logfile()
102
+
103
+
104
+ def register_static_file(app: FastAPI):
105
+ """
106
+ Static file interaction development model, production using nginx static resource service
107
+
108
+ :param app:
109
+ :return:
110
+ """
111
+ if settings.FASTAPI_STATIC_FILES:
112
+ import os
113
+
114
+ from fastapi.staticfiles import StaticFiles
115
+
116
+ if not os.path.exists(STATIC_DIR):
117
+ os.mkdir(STATIC_DIR)
118
+ app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
119
+
120
+
121
+ def register_middleware(app: FastAPI, name: str = "Parse name"):
122
+ """
123
+ Middleware, execution order from bottom to top
124
+
125
+ :param app:
126
+ :return:
127
+ """
128
+ # Metrics middleware (opt-in observability)
129
+ if settings.OBSERVABILITY_ENABLED:
130
+ from backend.utils.prometheus import PrometheusMiddleware
131
+
132
+ app.add_middleware(PrometheusMiddleware, app_name=settings.APP_NAME)
133
+
134
+ # Opera log (required)
135
+ app.add_middleware(OperaLogMiddleware)
136
+
137
+ # I18N translation middleware
138
+ app.add_middleware(I18nMiddleware)
139
+
140
+
141
+ app.add_middleware(
142
+ AuthenticationMiddleware, backend=JwtAuthMiddleware(), on_error=JwtAuthMiddleware.auth_exception_handler
143
+ )
144
+
145
+ # Access log
146
+ if settings.MIDDLEWARE_ACCESS:
147
+ from backend.middleware.access_middleware import AccessMiddleware
148
+
149
+ app.add_middleware(AccessMiddleware)
150
+
151
+ # State
152
+ app.add_middleware(StateMiddleware)
153
+
154
+ # Trace ID (required)
155
+ app.add_middleware(CorrelationIdMiddleware, validator=False)
156
+
157
+ # CORS: Always at the end
158
+ if settings.MIDDLEWARE_CORS:
159
+ from fastapi.middleware.cors import CORSMiddleware
160
+
161
+ app.add_middleware(
162
+ CORSMiddleware,
163
+ allow_origins=settings.CORS_ALLOWED_ORIGINS,
164
+ allow_credentials=True,
165
+ allow_methods=["*"],
166
+ allow_headers=["*"],
167
+ expose_headers=settings.CORS_EXPOSE_HEADERS,
168
+ )
169
+
170
+
171
+ def register_router(app: FastAPI, router: APIRouter):
172
+ """
173
+ routing
174
+
175
+ :param app: FastAPI
176
+ :return:
177
+ """
178
+ dependencies = [Depends(demo_site)] if settings.DEMO_MODE else None
179
+
180
+ # API
181
+ app.include_router(router, dependencies=dependencies)
182
+
183
+ # Extra
184
+ ensure_unique_route_names(app)
185
+ # simplify_operation_ids(app)
186
+
187
+
188
+ def register_page(app: FastAPI):
189
+ """
190
+ paging search
191
+
192
+ :param app:
193
+ :return:
194
+ """
195
+ add_pagination(app)
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,35 @@
1
+ from typing import Any
2
+ from sqlalchemy import select
3
+ from sqlalchemy.ext.asyncio import AsyncSession
4
+ from sqlalchemy.orm import selectinload
5
+ from sqlalchemy.sql import Select
6
+ from sqlalchemy_crud_plus.utils import parse_filters
7
+ from sqlalchemy_crud_plus.types import Model
8
+ from sqlalchemy_crud_plus import CRUDPlus
9
+
10
+
11
+
12
+
13
+ class CRUDBase(CRUDPlus[Model]):
14
+
15
+ def get_with_relationship(self, stmt: Select, populates: list[str] = [], sub_populates: list[Any] = []) -> Select:
16
+ for populate in populates:
17
+ stmt = stmt.options(selectinload(getattr(self.model, populate)), *sub_populates)
18
+
19
+ return stmt
20
+
21
+
22
+ async def select_model_by_column(self, session: AsyncSession, populates: list[str] = [], sub_populates: list[Any] = [], **kwargs) -> Model | None:
23
+ """
24
+ Query by column
25
+
26
+ :param session: The SQLAlchemy async session.
27
+ :param kwargs: Query expressions.
28
+ :return:
29
+ """
30
+ filters = parse_filters(self.model, **kwargs)
31
+ stmt = select(self.model).where(*filters)
32
+ stmt = self.get_with_relationship(stmt, populates=populates, sub_populates=sub_populates)
33
+ query = await session.execute(stmt)
34
+ return query.scalars().first()
35
+
@@ -0,0 +1,46 @@
1
+ from uuid import UUID
2
+
3
+ from sqlalchemy import Select
4
+ from sqlalchemy.ext.asyncio import AsyncSession
5
+ from backend.crud.crud_base import CRUDBase
6
+
7
+ from backend.models import CasbinRule
8
+ from backend.app.admin.schema.casbin_rule import DeleteAllPoliciesParam
9
+
10
+
11
+ class CRUDCasbin(CRUDBase[CasbinRule]):
12
+ async def get_list(self, ptype: str, sub: str) -> Select:
13
+ """
14
+ Getting a list of casbin policies
15
+
16
+ :param ptype:
17
+ :param sub:
18
+ :return:
19
+ """
20
+ return await self.select_order('id', 'desc', ptype=ptype, v0__like=f'%{sub}%')
21
+
22
+ async def delete_policies_by_sub(self, db: AsyncSession, sub: DeleteAllPoliciesParam) -> int:
23
+ """
24
+ Delete all P casbin policies for the role
25
+
26
+ :param db:
27
+ :param sub:
28
+ :return:
29
+ """
30
+ where_list = [sub.role]
31
+ if sub.uuid:
32
+ where_list.append(sub.uuid)
33
+ return await self.delete_model_by_column(db, allow_multiple=True, v0__mor={'eq': where_list})
34
+
35
+ async def delete_groups_by_uuid(self, db: AsyncSession, uuid: UUID) -> int:
36
+ """
37
+ Delete all G casbin policies for a user
38
+
39
+ :param db:
40
+ :param uuid:
41
+ :return:
42
+ """
43
+ return await self.delete_model_by_column(db, allow_multiple=True, v0=str(uuid))
44
+
45
+
46
+ casbin_dao: CRUDCasbin = CRUDCasbin(CasbinRule)
@@ -0,0 +1,58 @@
1
+ from sqlalchemy import Select
2
+ from sqlalchemy.ext.asyncio import AsyncSession
3
+ from sqlalchemy_crud_plus import CRUDPlus
4
+
5
+ from backend.models import LoginLog
6
+ from backend.app.admin.schema.login_log import CreateLoginLogParam
7
+
8
+
9
+ class CRUDLoginLog(CRUDPlus[LoginLog]):
10
+ async def get_list(self, username: str | None = None, status: int | None = None, ip: str | None = None) -> Select:
11
+ """
12
+ Get the list of login logs
13
+
14
+ :param username:
15
+ :param status:
16
+ :param ip:
17
+ :return:
18
+ """
19
+ filters = {}
20
+ if username is not None:
21
+ filters.update(username__like=f'%{username}%')
22
+ if status is not None:
23
+ filters.update(status=status)
24
+ if ip is not None:
25
+ filters.update(ip__like=f'%{ip}%')
26
+ return await self.select_order('created_time', 'desc', **filters)
27
+
28
+ async def create(self, db: AsyncSession, obj_in: CreateLoginLogParam) -> None:
29
+ """
30
+ Create login logs
31
+
32
+ :param db:
33
+ :param obj_in:
34
+ :return:
35
+ """
36
+ await self.create_model(db, obj_in, commit=True)
37
+
38
+ async def delete(self, db: AsyncSession, pk: list[int]) -> int:
39
+ """
40
+ Delete login logs
41
+
42
+ :param db:
43
+ :param pk:
44
+ :return:
45
+ """
46
+ return await self.delete_model_by_column(db, allow_multiple=True, id__in=pk)
47
+
48
+ async def delete_all(self, db: AsyncSession) -> int:
49
+ """
50
+ Delete all login logs
51
+
52
+ :param db:
53
+ :return:
54
+ """
55
+ return await self.delete_model_by_column(db, allow_multiple=True)
56
+
57
+
58
+ login_log_dao: CRUDLoginLog = CRUDLoginLog(LoginLog)
@@ -0,0 +1,58 @@
1
+ from sqlalchemy import Select
2
+ from sqlalchemy.ext.asyncio import AsyncSession
3
+ from backend.crud.crud_base import CRUDBase
4
+
5
+ from backend.models import OperaLog
6
+ from backend.app.admin.schema.opera_log import CreateOperaLogParam
7
+
8
+
9
+ class CRUDOperaLogDao(CRUDBase[OperaLog]):
10
+ async def get_list(self, username: str | None = None, status: int | None = None, ip: str | None = None) -> Select:
11
+ """
12
+ Getting a list of operation logs
13
+
14
+ :param username:
15
+ :param status:
16
+ :param ip:
17
+ :return:
18
+ """
19
+ filters = {}
20
+ if username is not None:
21
+ filters.update(username=f'%{username}%')
22
+ if status is not None:
23
+ filters.update(status=status)
24
+ if ip is not None:
25
+ filters.update(ip=f'%{ip}%')
26
+ return await self.select_order('created_time', 'desc', **filters)
27
+
28
+ async def create(self, db: AsyncSession, obj_in: CreateOperaLogParam) -> None:
29
+ """
30
+ Creating operation logs
31
+
32
+ :param db:
33
+ :param obj_in:
34
+ :return:
35
+ """
36
+ await self.create_model(db, obj_in)
37
+
38
+ async def delete(self, db: AsyncSession, pk: list[int]) -> int:
39
+ """
40
+ Delete operation log
41
+
42
+ :param db:
43
+ :param pk:
44
+ :return:
45
+ """
46
+ return await self.delete_model_by_column(db, allow_multiple=True, id__in=pk)
47
+
48
+ async def delete_all(self, db: AsyncSession) -> int:
49
+ """
50
+ Delete all operation logs
51
+
52
+ :param db:
53
+ :return:
54
+ """
55
+ return await self.delete_model_by_column(db, allow_multiple=True)
56
+
57
+
58
+ opera_log_dao: CRUDOperaLogDao = CRUDOperaLogDao(OperaLog)
@@ -0,0 +1,128 @@
1
+ from sqlalchemy import Sequence, desc, select
2
+ from sqlalchemy.ext.asyncio import AsyncSession
3
+ from sqlalchemy.sql import Select
4
+ from backend.crud.crud_base import CRUDBase
5
+
6
+ from backend.models import Role, Role
7
+ from backend.app.admin.schema.role import (
8
+ CreateRoleParam,
9
+ UpdateRoleParam,
10
+ )
11
+ from backend.models.user import User
12
+
13
+
14
+ class CRUDRole(CRUDBase[Role]):
15
+ async def get(self, db: AsyncSession, role_id: int) -> Role | None:
16
+ """
17
+ Getting Roles
18
+
19
+ :param db:
20
+ :param role_id:
21
+ :return:
22
+ """
23
+ return await self.select_model(db, role_id)
24
+
25
+ async def get(self, db, role_id: int) -> Role | None:
26
+ """
27
+ Get role by id
28
+
29
+ :param db:
30
+ :param role_id:
31
+ :return:
32
+ """
33
+ return await self.select_model(db, role_id)
34
+
35
+ async def get_all(self, db) -> Sequence[Role]:
36
+ """
37
+ Get all roles
38
+
39
+ :param db:
40
+ :return:
41
+ """
42
+ return await self.select_models(db)
43
+
44
+ async def get_user_roles(self, db, user_id: int) -> Sequence[Role]:
45
+ """
46
+ Get user roles
47
+
48
+ :param db:
49
+ :param user_id:
50
+ :return:
51
+ """
52
+ stmt = select(self.model).join(self.model.users).where(User.id == user_id)
53
+ roles = await db.execute(stmt)
54
+ return roles.scalars().all()
55
+
56
+ async def get_list(
57
+ self, name: str = None, data_scope: int = None, status: int = None
58
+ ) -> Select:
59
+ """
60
+ Get role list
61
+
62
+ :param name:
63
+ :param data_scope:
64
+ :param status:
65
+ :return:
66
+ """
67
+ stmt = (
68
+ select(self.model)
69
+ .order_by(desc(self.model.created_time))
70
+ )
71
+ where_list = []
72
+ if name:
73
+ where_list.append(self.model.name.like(f"%{name}%"))
74
+ if data_scope:
75
+ where_list.append(self.model.data_scope == data_scope)
76
+ if status is not None:
77
+ where_list.append(self.model.status == status)
78
+ if where_list:
79
+ stmt = stmt.where(*where_list)
80
+ return stmt
81
+
82
+ async def get_by_name(self, db, name: str) -> Role | None:
83
+ """
84
+ Get role by name
85
+
86
+ :param db:
87
+ :param name:
88
+ :return:
89
+ """
90
+ roles = await self.select_model_by_column(db, name=name)
91
+
92
+ return roles
93
+
94
+ async def create(self, db, obj_in: CreateRoleParam) -> None:
95
+ """
96
+ Creating roles
97
+
98
+ :param db:
99
+ :param obj_in:
100
+ :return:
101
+ """
102
+ await self.create_model(db, obj_in)
103
+
104
+ async def update(self, db, role_id: int, obj_in: UpdateRoleParam) -> int:
105
+ """
106
+ Updating roles
107
+
108
+ :param db:
109
+ :param role_id:
110
+ :param obj_in:
111
+ :return:
112
+ """
113
+ return await self.update_model(db, role_id, obj_in)
114
+
115
+ async def delete(self, db, role_id: list[int]) -> int:
116
+ """
117
+ Delete roles
118
+
119
+ :param db:
120
+ :param role_id:
121
+ :return:
122
+ """
123
+ return await self.delete_model_by_column(
124
+ db, allow_multiple=True, id__in=role_id
125
+ )
126
+
127
+
128
+ role_dao: CRUDRole = CRUDRole(Role)