arpakitlib 1.8.111__py3-none-any.whl → 1.8.113__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 (27) hide show
  1. arpakitlib/_arpakit_project_template_v_5/arpakitlib_project_template_info.json +1 -1
  2. arpakitlib/_arpakit_project_template_v_5/project/api/create_first_data.py +64 -0
  3. arpakitlib/_arpakit_project_template_v_5/project/api/event.py +4 -0
  4. arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_operation.py +1 -5
  5. arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_story_log.py +1 -5
  6. arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_user.py +0 -5
  7. arpakitlib/_arpakit_project_template_v_5/project/api/start_api.py +26 -0
  8. arpakitlib/_arpakit_project_template_v_5/project/core/easy_openai_api_client.py +2 -2
  9. arpakitlib/_arpakit_project_template_v_5/project/core/settings.py +12 -0
  10. arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/event.py +1 -0
  11. arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/api_key.py +1 -0
  12. arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/story_log.py +0 -1
  13. arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/user.py +1 -2
  14. arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/user_token.py +1 -2
  15. arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/verification_code.py +10 -1
  16. arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/start_sqladmin.py +19 -0
  17. arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_1.py +18 -2
  18. arpakitlib/_arpakit_project_template_v_5/project/tg_bot_notifier/__init__.py +0 -0
  19. arpakitlib/_arpakit_project_template_v_5/project/tg_bot_notifier/blank.py +20 -0
  20. arpakitlib/_arpakit_project_template_v_5/project/tg_bot_notifier/tg_bot_notifier.py +24 -0
  21. arpakitlib/_arpakit_project_template_v_5/project/util/send_email.py +81 -0
  22. {arpakitlib-1.8.111.dist-info → arpakitlib-1.8.113.dist-info}/METADATA +1 -1
  23. {arpakitlib-1.8.111.dist-info → arpakitlib-1.8.113.dist-info}/RECORD +26 -20
  24. arpakitlib/_arpakit_project_template_v_5/project/business_service/create_first_admin.py +0 -37
  25. {arpakitlib-1.8.111.dist-info → arpakitlib-1.8.113.dist-info}/LICENSE +0 -0
  26. {arpakitlib-1.8.111.dist-info → arpakitlib-1.8.113.dist-info}/WHEEL +0 -0
  27. {arpakitlib-1.8.111.dist-info → arpakitlib-1.8.113.dist-info}/entry_points.txt +0 -0
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "arpakitlib_project_template_version": "5",
3
- "arpakitlib_project_template_subversion": "26"
3
+ "arpakitlib_project_template_subversion": "27"
4
4
  }
@@ -0,0 +1,64 @@
1
+ import logging
2
+
3
+ from project.core.util import setup_logging
4
+ from project.sqlalchemy_db_.sqlalchemy_db import get_cached_sqlalchemy_db
5
+ from project.sqlalchemy_db_.sqlalchemy_model import UserDBM, ApiKeyDBM, UserTokenDBM
6
+
7
+ _logger = logging.getLogger(__name__)
8
+
9
+
10
+ def create_first_data_for_api():
11
+ with get_cached_sqlalchemy_db().new_session() as session:
12
+ user_dbm = (
13
+ session
14
+ .query(UserDBM)
15
+ .filter(UserDBM.roles.any(UserDBM.Roles.admin))
16
+ .first()
17
+ )
18
+ if user_dbm is None:
19
+ user_dbm = UserDBM(
20
+ username="admin",
21
+ roles=[UserDBM.Roles.client, UserDBM.Roles.admin],
22
+ password="admin",
23
+ )
24
+ session.add(user_dbm)
25
+ session.commit()
26
+ _logger.info("admin was created")
27
+
28
+ user_token_dbm = (
29
+ session
30
+ .query(UserTokenDBM)
31
+ .filter(UserTokenDBM.user_id == user_dbm.id)
32
+ .first()
33
+ )
34
+ if user_token_dbm is None:
35
+ user_token_dbm = UserTokenDBM(
36
+ value="1",
37
+ user_id=user_dbm.id
38
+ )
39
+ session.add(user_token_dbm)
40
+ session.commit()
41
+ _logger.info("admin token was created")
42
+
43
+ api_key_dbm = (
44
+ session
45
+ .query(ApiKeyDBM)
46
+ .first()
47
+ )
48
+ if api_key_dbm is None:
49
+ api_key_dbm = ApiKeyDBM(
50
+ value="1",
51
+ title="First api key"
52
+ )
53
+ session.add(api_key_dbm)
54
+ session.commit()
55
+ _logger.info("api key was created")
56
+
57
+
58
+ def command():
59
+ setup_logging()
60
+ create_first_data_for_api()
61
+
62
+
63
+ if __name__ == '__main__':
64
+ command()
@@ -2,6 +2,7 @@ import logging
2
2
  from typing import Callable
3
3
 
4
4
  from arpakitlib.ar_base_worker_util import safe_run_worker_in_background, SafeRunInBackgroundModes
5
+ from project.api.create_first_data import create_first_data_for_api
5
6
  from project.core.cache_file_storage_in_dir import get_cached_cache_file_storage_in_dir
6
7
  from project.core.dump_file_storage_in_dir import get_cached_dump_file_storage_in_dir
7
8
  from project.core.media_file_storage_in_dir import get_cached_media_file_storage_in_dir
@@ -41,6 +42,9 @@ async def async_startup_api_event():
41
42
  ):
42
43
  get_cached_json_db().init()
43
44
 
45
+ if get_cached_sqlalchemy_db() is not None:
46
+ create_first_data_for_api()
47
+
44
48
  if get_cached_settings().api_start_operation_executor_worker:
45
49
  _ = safe_run_worker_in_background(
46
50
  worker=create_operation_executor_worker(),
@@ -34,12 +34,10 @@ async def _(
34
34
  ])),
35
35
  filter_id: int | None = fastapi.Query(default=None),
36
36
  filter_long_id: str | None = fastapi.Query(default=None),
37
- filter_slug: str | None = fastapi.Query(default=None),
38
37
  ):
39
38
  filter_long_id = make_none_if_blank(strip_if_not_none(filter_long_id))
40
- filter_slug = make_none_if_blank(strip_if_not_none(filter_slug))
41
39
 
42
- if filter_id is None and filter_long_id is None and filter_slug is None:
40
+ if filter_id is None and filter_long_id is None:
43
41
  return None
44
42
 
45
43
  query = sqlalchemy.select(OperationDBM)
@@ -47,8 +45,6 @@ async def _(
47
45
  query = query.filter(OperationDBM.id == filter_id)
48
46
  if filter_long_id is not None:
49
47
  query = query.filter(OperationDBM.long_id == filter_long_id)
50
- if filter_slug is not None:
51
- query = query.filter(OperationDBM.slug == filter_slug)
52
48
 
53
49
  async with get_cached_sqlalchemy_db().new_async_session() as async_session:
54
50
  result = await async_session.scalar(query)
@@ -34,12 +34,10 @@ async def _(
34
34
  ])),
35
35
  filter_id: int | None = fastapi.Query(default=None),
36
36
  filter_long_id: str | None = fastapi.Query(default=None),
37
- filter_slug: str | None = fastapi.Query(default=None),
38
37
  ):
39
38
  filter_long_id = make_none_if_blank(strip_if_not_none(filter_long_id))
40
- filter_slug = make_none_if_blank(strip_if_not_none(filter_slug))
41
39
 
42
- if filter_id is None and filter_long_id is None and filter_slug is None:
40
+ if filter_id is None and filter_long_id is None:
43
41
  return None
44
42
 
45
43
  query = sqlalchemy.select(StoryLogDBM)
@@ -47,8 +45,6 @@ async def _(
47
45
  query = query.filter(StoryLogDBM.id == filter_id)
48
46
  if filter_long_id is not None:
49
47
  query = query.filter(StoryLogDBM.long_id == filter_long_id)
50
- if filter_slug is not None:
51
- query = query.filter(StoryLogDBM.slug == filter_slug)
52
48
 
53
49
  async with get_cached_sqlalchemy_db().new_async_session() as async_session:
54
50
  result = await async_session.scalar(query)
@@ -34,20 +34,17 @@ async def _(
34
34
  ])),
35
35
  filter_id: int | None = fastapi.Query(default=None),
36
36
  filter_long_id: str | None = fastapi.Query(default=None),
37
- filter_slug: str | None = fastapi.Query(default=None),
38
37
  filter_email: str | None = fastapi.Query(default=None),
39
38
  filter_username: str | None = fastapi.Query(default=None),
40
39
  filter_tg_id: int | None = fastapi.Query(default=None),
41
40
  ):
42
41
  filter_long_id = make_none_if_blank(strip_if_not_none(filter_long_id))
43
- filter_slug = make_none_if_blank(strip_if_not_none(filter_slug))
44
42
  filter_email = make_none_if_blank(strip_if_not_none(filter_email))
45
43
  filter_username = make_none_if_blank(strip_if_not_none(filter_username))
46
44
 
47
45
  if (
48
46
  filter_id is None
49
47
  and filter_long_id is None
50
- and filter_slug is None
51
48
  and filter_email is None
52
49
  and filter_username is None
53
50
  and filter_tg_id is None
@@ -59,8 +56,6 @@ async def _(
59
56
  query = query.filter(UserDBM.id == filter_id)
60
57
  if filter_long_id is not None:
61
58
  query = query.filter(UserDBM.long_id == filter_long_id)
62
- if filter_slug is not None:
63
- query = query.filter(UserDBM.slug == filter_slug)
64
59
  if filter_email is not None:
65
60
  query = query.filter(UserDBM.email == filter_email)
66
61
  if filter_username is not None:
@@ -0,0 +1,26 @@
1
+ import uvicorn
2
+
3
+ from arpakitlib.ar_base_worker_util import safe_run_worker_in_background, SafeRunInBackgroundModes
4
+ from project.core.settings import get_cached_settings
5
+ from project.core.util import setup_logging
6
+ from project.operation_execution.scheduled_operation_creator_worker import create_scheduled_operation_creator_worker
7
+
8
+
9
+ def __command():
10
+ setup_logging()
11
+ if get_cached_settings().api_start_scheduled_operation_creator_worker:
12
+ _ = safe_run_worker_in_background(
13
+ worker=create_scheduled_operation_creator_worker(),
14
+ mode=SafeRunInBackgroundModes.thread
15
+ )
16
+ uvicorn.run(
17
+ "project.api.asgi:app",
18
+ port=get_cached_settings().api_port,
19
+ host="localhost",
20
+ workers=1,
21
+ reload=False
22
+ )
23
+
24
+
25
+ if __name__ == '__main__':
26
+ __command()
@@ -2,10 +2,10 @@ import asyncio
2
2
  from functools import lru_cache
3
3
 
4
4
  import httpx
5
- from arpakitlib.ar_logging_util import setup_normal_logging
6
- from arpakitlib.ar_openai_api_client_util import EasyOpenAIAPIClient
7
5
  from openai import OpenAI, AsyncOpenAI
8
6
 
7
+ from arpakitlib.ar_logging_util import setup_normal_logging
8
+ from arpakitlib.ar_openai_api_client_util import EasyOpenAIAPIClient
9
9
  from project.core.settings import get_cached_settings
10
10
 
11
11
 
@@ -168,6 +168,14 @@ class Settings(SimpleSettings):
168
168
 
169
169
  local_timezone: str | None = None
170
170
 
171
+ email_smtp_user: str | None = None
172
+
173
+ email_smtp_password: str | None = None
174
+
175
+ email_smtp_port: int | None = 465
176
+
177
+ email_smtp_hostname: str | None = "smtp.yandex.ru"
178
+
171
179
  @property
172
180
  def local_timezone_as_pytz(self) -> Any:
173
181
  raise_for_type(self.local_timezone, str)
@@ -177,6 +185,10 @@ class Settings(SimpleSettings):
177
185
 
178
186
  openai_api_base_url: str | None = "https://api.proxyapi.ru/openai/v1"
179
187
 
188
+ tg_bot_notifier_token: str | None = None
189
+
190
+ tg_bot_notifier_proxy_url: str | None = None
191
+
180
192
 
181
193
  @lru_cache()
182
194
  def get_cached_settings() -> Settings:
@@ -1,6 +1,7 @@
1
1
  import logging
2
2
  from typing import Callable
3
3
 
4
+ from project.business_service.create_first_data import create_first_admin_with_api_key
4
5
  from project.core.settings import get_cached_settings
5
6
  from project.sqlalchemy_db_.sqlalchemy_db import get_cached_sqlalchemy_db
6
7
 
@@ -41,6 +41,7 @@ class ApiKeyMV(SimpleMV, model=ApiKeyDBM):
41
41
  ]
42
42
  column_searchable_list = [
43
43
  ApiKeyDBM.id,
44
+ ApiKeyDBM.long_id,
44
45
  ApiKeyDBM.value,
45
46
  ]
46
47
  column_formatters = {
@@ -33,7 +33,6 @@ class StoryLogMV(SimpleMV, model=StoryLogDBM):
33
33
  column_searchable_list = [
34
34
  StoryLogDBM.id,
35
35
  StoryLogDBM.long_id,
36
- StoryLogDBM.slug,
37
36
  ]
38
37
  column_formatters = {
39
38
  StoryLogDBM.creation_dt: lambda m, _: format_datetime_(m.creation_dt),
@@ -43,7 +43,7 @@ class UserMV(SimpleMV, model=UserDBM):
43
43
  form_args = {
44
44
  UserDBM.roles.key: {
45
45
  "choices": [(role, role) for role in UserDBM.Roles.values_list()],
46
- "description": "Choose user roles"
46
+ "description": "Choose roles"
47
47
  }
48
48
  }
49
49
  column_sortable_list = sqlalchemy.inspect(UserDBM).columns
@@ -55,7 +55,6 @@ class UserMV(SimpleMV, model=UserDBM):
55
55
  UserDBM.long_id,
56
56
  UserDBM.email,
57
57
  UserDBM.username,
58
- UserDBM.password,
59
58
  UserDBM.tg_id
60
59
  ]
61
60
  column_formatters = {
@@ -34,7 +34,6 @@ class UserTokenMV(SimpleMV, model=UserTokenDBM):
34
34
  column_searchable_list = [
35
35
  UserTokenDBM.id,
36
36
  UserTokenDBM.long_id,
37
- UserTokenDBM.slug,
38
37
  UserTokenDBM.value,
39
38
  ]
40
39
  column_formatters = {
@@ -47,7 +46,7 @@ class UserTokenMV(SimpleMV, model=UserTokenDBM):
47
46
  }
48
47
  form_ajax_refs = {
49
48
  UserTokenDBM.user.key: {
50
- "fields": [UserDBM.id.key, UserDBM.email.key],
49
+ "fields": [UserDBM.id.key, UserDBM.email.key, UserDBM.username.key],
51
50
  "placeholder": "Search by id or email",
52
51
  "minimum_input_length": 1,
53
52
  "page_size": 10,
@@ -5,7 +5,7 @@ from sqladmin.fields import SelectField
5
5
 
6
6
  from project.sqladmin_.model_view import SimpleMV
7
7
  from project.sqladmin_.util.etc import format_datetime_, format_json_for_preview_, format_json_
8
- from project.sqlalchemy_db_.sqlalchemy_model import VerificationCodeDBM
8
+ from project.sqlalchemy_db_.sqlalchemy_model import VerificationCodeDBM, UserDBM
9
9
 
10
10
 
11
11
  class VerificationCodeMV(SimpleMV, model=VerificationCodeDBM):
@@ -48,6 +48,7 @@ class VerificationCodeMV(SimpleMV, model=VerificationCodeDBM):
48
48
  ]
49
49
  column_searchable_list = [
50
50
  VerificationCodeDBM.id,
51
+ VerificationCodeDBM.long_id,
51
52
  VerificationCodeDBM.value,
52
53
  VerificationCodeDBM.recipient
53
54
  ]
@@ -59,3 +60,11 @@ class VerificationCodeMV(SimpleMV, model=VerificationCodeDBM):
59
60
  VerificationCodeDBM.creation_dt: lambda m, _: format_datetime_(m.creation_dt),
60
61
  VerificationCodeDBM.extra_data: lambda m, a: format_json_(m.extra_data),
61
62
  }
63
+ form_ajax_refs = {
64
+ VerificationCodeDBM.user.key: {
65
+ "fields": [UserDBM.id.key, UserDBM.email.key, UserDBM.username.key],
66
+ "placeholder": "Search by id or email",
67
+ "minimum_input_length": 1,
68
+ "page_size": 10,
69
+ }
70
+ }
@@ -0,0 +1,19 @@
1
+ import uvicorn
2
+
3
+ from project.core.settings import get_cached_settings
4
+ from project.core.util import setup_logging
5
+
6
+
7
+ def __command():
8
+ setup_logging()
9
+ uvicorn.run(
10
+ "project.sqladmin_.asgi:app",
11
+ port=get_cached_settings().sqladmin_port,
12
+ host="localhost",
13
+ workers=1,
14
+ reload=False
15
+ )
16
+
17
+
18
+ if __name__ == '__main__':
19
+ __command()
@@ -1,6 +1,7 @@
1
1
  import asyncio
2
2
  import logging
3
3
 
4
+ from arpakitlib.ar_datetime_util import now_utc_dt
4
5
  from project.core.settings import get_cached_settings
5
6
  from project.core.util import setup_logging
6
7
  from project.sqlalchemy_db_.sqlalchemy_db import get_cached_sqlalchemy_db
@@ -31,13 +32,28 @@ def make_test_data_1():
31
32
  is_active=True,
32
33
  is_verified=True,
33
34
  password="123",
34
- tg_id=269870432
35
+ tg_id=269870432,
36
+ tg_bot_last_action_dt=now_utc_dt(),
37
+ tg_data={
38
+ "id": 269870432,
39
+ "is_bot": False,
40
+ "first_name": "Арсен",
41
+ "last_name": "Arsen",
42
+ "username": "arpakit",
43
+ "language_code": "en",
44
+ "is_premium": True,
45
+ "added_to_attachment_menu": None,
46
+ "can_join_groups": None,
47
+ "can_read_all_group_messages": None,
48
+ "supports_inline_queries": None,
49
+ "can_connect_to_business": None
50
+ }
35
51
  )
36
52
  session.add(arpakit_user)
37
53
  session.commit()
38
54
  _logger.info(arpakit_user)
39
55
 
40
- for i in range(1000):
56
+ for i in range(100):
41
57
  user_token_dbm = UserTokenDBM(user_id=arpakit_user.id, value=str(i))
42
58
  session.add(user_token_dbm)
43
59
  _logger.info(user_token_dbm)
@@ -0,0 +1,20 @@
1
+ from functools import lru_cache
2
+
3
+ from arpakitlib.ar_blank_util import BaseBlank
4
+
5
+
6
+ class TgBotNotifierBlank(BaseBlank):
7
+ pass
8
+
9
+
10
+ @lru_cache()
11
+ def get_cached_rus_tg_bot_notifier_blank() -> TgBotNotifierBlank:
12
+ return TgBotNotifierBlank(lang=TgBotNotifierBlank.Languages.rus)
13
+
14
+
15
+ def __example():
16
+ print(get_cached_rus_tg_bot_notifier_blank().hello_world())
17
+
18
+
19
+ if __name__ == '__main__':
20
+ __example()
@@ -0,0 +1,24 @@
1
+ import aiogram
2
+ from aiogram.client.default import DefaultBotProperties
3
+ from aiogram.client.session.aiohttp import AiohttpSession
4
+ from aiogram.enums import ParseMode
5
+
6
+ from project.core.settings import get_cached_settings
7
+
8
+
9
+ def create_tg_bot_notifier() -> aiogram.Bot | None:
10
+ if get_cached_settings().tg_bot_notifier_token is None:
11
+ return None
12
+ session: AiohttpSession | None = None
13
+ if get_cached_settings().tg_bot_notifier_proxy_url:
14
+ session = AiohttpSession(proxy=get_cached_settings().tg_bot_notifier_proxy_url)
15
+ tg_bot = aiogram.Bot(
16
+ token=get_cached_settings().tg_bot_notifier_token,
17
+ default=DefaultBotProperties(
18
+ parse_mode=ParseMode.HTML,
19
+ disable_notification=False,
20
+ link_preview_is_disabled=True
21
+ ),
22
+ session=session
23
+ )
24
+ return tg_bot
@@ -0,0 +1,81 @@
1
+ import asyncio
2
+ import logging
3
+ import smtplib
4
+ from email.message import EmailMessage
5
+
6
+ import aiosmtplib
7
+
8
+ from project.core.settings import get_cached_settings
9
+ from project.core.util import setup_logging
10
+
11
+ _logger = logging.getLogger(__name__)
12
+
13
+
14
+ def send_email(
15
+ *, to_email: str, subject: str = "Hello world", html_content: str,
16
+ emulate: bool = False
17
+ ):
18
+ to_email = to_email.strip()
19
+
20
+ if emulate:
21
+ _logger.info(f"emulate email sending, {to_email=}, {subject=}, {html_content=}")
22
+ return
23
+
24
+ message = EmailMessage()
25
+ message["From"] = get_cached_settings().email_smtp_user
26
+ message["To"] = to_email
27
+ message["Subject"] = subject
28
+ message.add_alternative(html_content, subtype="html")
29
+
30
+ with smtplib.SMTP_SSL(
31
+ get_cached_settings().email_smtp_hostname,
32
+ get_cached_settings().email_smtp_port
33
+ ) as server:
34
+ server.login(
35
+ get_cached_settings().email_smtp_user,
36
+ get_cached_settings().email_smtp_password
37
+ )
38
+ server.send_message(message)
39
+
40
+ _logger.info(f"email was send, {to_email=}")
41
+
42
+
43
+ async def async_send_email(
44
+ *,
45
+ to_email: str, subject: str = "Hello world", html_content: str,
46
+ emulate: bool = False
47
+ ):
48
+ to_email = to_email.strip()
49
+
50
+ if emulate:
51
+ _logger.info(f"emulate email sending, {to_email=}, {subject=}, {html_content=}")
52
+ return
53
+
54
+ message = EmailMessage()
55
+ message["From"] = get_cached_settings().email_smtp_user
56
+ message["To"] = to_email
57
+ message["Subject"] = subject
58
+ message.add_alternative(html_content, subtype="html")
59
+
60
+ await aiosmtplib.send(
61
+ message,
62
+ hostname=get_cached_settings().email_smtp_hostname,
63
+ port=get_cached_settings().email_smtp_port,
64
+ username=get_cached_settings().email_smtp_user,
65
+ password=get_cached_settings().email_smtp_password,
66
+ use_tls=True
67
+ )
68
+
69
+ _logger.info(f"email was send, {to_email=}")
70
+
71
+
72
+ async def __async_example():
73
+ setup_logging()
74
+ send_email(
75
+ to_email="arpakit@gmail.com",
76
+ html_content="Hello world 2"
77
+ )
78
+
79
+
80
+ if __name__ == '__main__':
81
+ asyncio.run(__async_example())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: arpakitlib
3
- Version: 1.8.111
3
+ Version: 1.8.113
4
4
  Summary: arpakitlib
5
5
  License: Apache-2.0
6
6
  Keywords: arpakitlib,arpakit,arpakit-company,arpakitcompany,arpakit_company
@@ -8,7 +8,7 @@ arpakitlib/_arpakit_project_template_v_5/alembic/env.py,sha256=Qesmnj5A2kB-Doeuf
8
8
  arpakitlib/_arpakit_project_template_v_5/alembic/script.py.mako,sha256=MEqL-2qATlST9TAOeYgscMn1uy6HUS9NFvDgl93dMj8,635
9
9
  arpakitlib/_arpakit_project_template_v_5/alembic/versions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  arpakitlib/_arpakit_project_template_v_5/alembic.ini,sha256=8fuyeEvGBiPGbxEFy8ISBV3xX_fgVmuhEGpB10_B5Uo,3733
11
- arpakitlib/_arpakit_project_template_v_5/arpakitlib_project_template_info.json,sha256=o3UxTcbS0YBkewD0pMMAWC8bJGs-V6tzvpFhgw0useE,98
11
+ arpakitlib/_arpakit_project_template_v_5/arpakitlib_project_template_info.json,sha256=R-BkDM1StRfEarU7UEwPZaxaGv7vHvTAGteM3_evSUQ,98
12
12
  arpakitlib/_arpakit_project_template_v_5/command/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  arpakitlib/_arpakit_project_template_v_5/command/alembic_history.sh,sha256=OMnDNtHIksGh9iavWnzbtxcudZW4vjdcISsBXvzZSPw,22
14
14
  arpakitlib/_arpakit_project_template_v_5/command/alembic_revision_autogenerate.sh,sha256=yW2i-SBOtBx15Ya0poVQqKkJM5t2JZp06r9AEW-DmGE,46
@@ -89,7 +89,8 @@ arpakitlib/_arpakit_project_template_v_5/project/api/blank/client.py,sha256=rvJK
89
89
  arpakitlib/_arpakit_project_template_v_5/project/api/blank/common.py,sha256=ug1FylE_CVC5eij-u4nh-IHNO-gwkbBGo5KgyWDujC8,91
90
90
  arpakitlib/_arpakit_project_template_v_5/project/api/const.py,sha256=J9bqaRRiIc3RLn6SJTvdfDvFrSsM_Ixii9t2M8dA5Jc,433
91
91
  arpakitlib/_arpakit_project_template_v_5/project/api/create_api_app.py,sha256=fRYjpKEB5pMpFtWEhUe84mVvaFBKQ2WU5BTwCpb0J2Y,2861
92
- arpakitlib/_arpakit_project_template_v_5/project/api/event.py,sha256=xKfJ3UnOx_g1s7KNZjWRp0eZbVRTsSlyJhT3wkfwT6k,2414
92
+ arpakitlib/_arpakit_project_template_v_5/project/api/create_first_data.py,sha256=sc98-xW74QbhFCT6AW5-fUJVd8RLRxClAOEW5-ec9T0,1815
93
+ arpakitlib/_arpakit_project_template_v_5/project/api/event.py,sha256=2DqXb8-iiSMoyh5OJI7nf53N5Bij5HfnFVrbLlI8G3w,2566
93
94
  arpakitlib/_arpakit_project_template_v_5/project/api/exception.py,sha256=cNZaI2DacGLl8Hyn1qIfFpVjvQzOQjwXWsVW4auBrCo,1280
94
95
  arpakitlib/_arpakit_project_template_v_5/project/api/exception_handler.py,sha256=TEzkCNOg_TAELRTZgLtblVagSaHf-vego_oH5FNCbcs,11179
95
96
  arpakitlib/_arpakit_project_template_v_5/project/api/openapi_ui.py,sha256=PLhH-W6zDViO-75AGCs8Vq3IoyHChdqwBYAqLvdQN0U,904
@@ -102,13 +103,13 @@ arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/create_operati
102
103
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_arpakitlib_project_template_info.py,sha256=c4HAHSivR8viAlHVyTut4VaKNkYsYiabE833FsUl9Yk,1265
103
104
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_auth_data.py,sha256=Hpjkucwnb2LtytWpMMA2WMROY2cTLn0q_tnUFijk0so,1195
104
105
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_log_file.py,sha256=rzEPco45I-4FzrlbI3z5B-smhrHFIVIsDiHtTULoE4g,1162
105
- arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_operation.py,sha256=uo3QK4Rw8V0YjMbCeymC6JZF2-qkMay3ofZlxBC3-S0,2291
106
+ arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_operation.py,sha256=cOG0c2s6grwvlN4xxXNyRVY28yI9u1xOryRt0fNHcko,2040
106
107
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_operation_allowed_statuses.py,sha256=eN-1XHeeSkgSTmYLldV-8uAY8qEmdUVCfvY2A5IHtw0,1096
107
108
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_operation_allowed_types.py,sha256=R5d3lZCHQNadPzG77WbJbLFQwTwPFU3l7BLYUlIOA6c,1090
108
109
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_settings.py,sha256=UhTWDrBkZHqkbqanDMr6Q4vZibDBeCIrVNzAInzjR8o,1157
109
110
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_sqlalchemy_db_table_name_to_amount.py,sha256=H6D9gEhbSKEwKeYj2HAyk948-sPvhxRark_Iqq67Jzk,1201
110
- arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_story_log.py,sha256=XEVouJSYgEIa0y6ujwfv26tAd6M-tMixOQZCxFUnHec,2283
111
- arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_user.py,sha256=ChsorTfFI03PzJfvcKU4mSHMTXuIrphXgoZBft6nMy4,3021
111
+ arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_story_log.py,sha256=sK0FvNzoG-pE5rD2Q62t6yK5Bx1Y2JZA_04sOk14loQ,2033
112
+ arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/get_user.py,sha256=lBTR7eyjVbf0I8yG1yTovlrz2H4h-6O3wggQLsMPdsw,2763
112
113
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/init_sqlalchemy_db.py,sha256=HUDaDeyb5ldpiEaA2mJIsAuGF6H-XupGvKfxjrkxMTE,1333
113
114
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/main_router.py,sha256=pu5-H9JlXhsVrY4a2ajbgeTbPo9ijIGSiq7J1Q77QT0,2479
114
115
  arpakitlib/_arpakit_project_template_v_5/project/api/router/admin/make_test_data_1.py,sha256=tITqtXW2C7od04_ECQudR_5kupVoKrYVnUVU2YcZp-g,1178
@@ -158,9 +159,9 @@ arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/general/api_key.
158
159
  arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/general/common.py,sha256=y-p4QJhvKnFL1I6ud3m_nzE0xtreT3CNApPkkkLAbG0,541
159
160
  arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/general/user.py,sha256=pHNtMOXZCSSpobetiKRKveEX6fPoywI5y7uQf9_WrBk,1055
160
161
  arpakitlib/_arpakit_project_template_v_5/project/api/schema/out/general/user_token.py,sha256=iiuZXu_zo3FJX0W5qyyMGasUx-_d32yjqc_2KY3xpUA,513
162
+ arpakitlib/_arpakit_project_template_v_5/project/api/start_api.py,sha256=fl-dkm2I3ModQXjGG6VrP6vUFciEcRW_ORFG3VX8jH8,821
161
163
  arpakitlib/_arpakit_project_template_v_5/project/api/util.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
162
164
  arpakitlib/_arpakit_project_template_v_5/project/business_service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
163
- arpakitlib/_arpakit_project_template_v_5/project/business_service/create_first_admin.py,sha256=2TzUxP8XY1ijTMXzpjfwelWgtqDmuX9_VmN915cvfkI,959
164
165
  arpakitlib/_arpakit_project_template_v_5/project/business_service/hello_world.py,sha256=lvWlVF6SlnC33swSCd-_QK6guxBg50myOd8cPS7hZrA,251
165
166
  arpakitlib/_arpakit_project_template_v_5/project/business_service/remove_operations.py,sha256=E2F8xonPeZovKKOHv-XDmsQUHvks8A6R89PVhF_pAQI,1780
166
167
  arpakitlib/_arpakit_project_template_v_5/project/celery_/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -168,10 +169,10 @@ arpakitlib/_arpakit_project_template_v_5/project/core/__init__.py,sha256=47DEQpj
168
169
  arpakitlib/_arpakit_project_template_v_5/project/core/cache_file_storage_in_dir.py,sha256=0lKPKvrs30DlAZwNS5ydPsQ9ETFLBjZqEcNv8LoQVCU,623
169
170
  arpakitlib/_arpakit_project_template_v_5/project/core/const.py,sha256=hgiiPIYL9543-eEnNAhZWYgX7ZzLKjOqRD0skkROSOw,951
170
171
  arpakitlib/_arpakit_project_template_v_5/project/core/dump_file_storage_in_dir.py,sha256=u3-vStMGaseMsRLuJmQK04UDhaez9vw6o5jyHb1fwNg,617
171
- arpakitlib/_arpakit_project_template_v_5/project/core/easy_openai_api_client.py,sha256=NAwu0e7m4m2OVcZC0KBbgjiNxKmpIUofBzwTRbC1GBQ,1219
172
+ arpakitlib/_arpakit_project_template_v_5/project/core/easy_openai_api_client.py,sha256=G4J9s0gerNlnvl1LvaWSYy1gdvaMbxyz0ZP35U9nx_Q,1219
172
173
  arpakitlib/_arpakit_project_template_v_5/project/core/jinja2_templates.py,sha256=jCNLaBauGC7YNvZdTLNHuPp7hmRGt94O23Skg6ewo7o,352
173
174
  arpakitlib/_arpakit_project_template_v_5/project/core/media_file_storage_in_dir.py,sha256=fMofTsfJtA8pp5lEUhucEUu3PBsmj-elaRZzExDsdLI,623
174
- arpakitlib/_arpakit_project_template_v_5/project/core/settings.py,sha256=NlbGFZCR98hytoigP4E5TjazIUJt8NPSI0NZOmQ365A,5995
175
+ arpakitlib/_arpakit_project_template_v_5/project/core/settings.py,sha256=BO6AgjZcK2pwClQFjabtuBObY0bvQ6NWbrrqvT2Kc_c,6270
175
176
  arpakitlib/_arpakit_project_template_v_5/project/core/util.py,sha256=1ha9UrguVPsTSjoMHhVZVCD0_mNBfhIDGEvcG1nA4Zw,667
176
177
  arpakitlib/_arpakit_project_template_v_5/project/json_db/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
177
178
  arpakitlib/_arpakit_project_template_v_5/project/json_db/json_db.py,sha256=tBML-z4Y7uY8f_0ggcxvlDNt15Sf93Jr_OUeHwWxqOA,724
@@ -230,15 +231,16 @@ arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/add_admin_in_app.py,s
230
231
  arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/admin_authorize.py,sha256=tmvYx5hFO2RqHmhKktpMRJaBuT6vDHBOsQujihO7sMw,4983
231
232
  arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/asgi.py,sha256=DRlRPkcOGXOccfP73oKEXolZTsc5VWdQgEG-qoW03ms,99
232
233
  arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/create_sqladmin_app.py,sha256=x5F8--5KA4cmTrb6kAAmp6fVd2TiqxPOzxqUkSEhSG4,1298
233
- arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/event.py,sha256=LjAUYNlsX9Sj_QLMzYuTQbbYYbIMHhbsSjTXt-G7lOE,849
234
+ arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/event.py,sha256=JhaCB_dW4YDQ5B8TlqI06qp_KVSiHuQefdLmhqoIdEI,936
234
235
  arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/__init__.py,sha256=dc_swzjkRDj85SWQ3cGGgsrp_cq5evUYQYUg0g7C5nw,435
235
- arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/api_key.py,sha256=VZKCG2GQworbmB_PPHPU10qMf5IThP0LN27k50XlHlg,1570
236
+ arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/api_key.py,sha256=VTpepKLCKrPnftGD-8Ibp75S0dwUrLlUytRfcXDDcKg,1597
236
237
  arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/common.py,sha256=StdbfHZ92qAP-l2lnvAeyYCaZuMHKskHq1E19zJh6MA,2471
237
238
  arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/operation.py,sha256=4BFJEp_yIpZltfEjsBC__J_BfgIBYzOc6LeoWFxP1MI,2785
238
- arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/story_log.py,sha256=8N9ahbCzNVczqgO_g0luRqP8luCv5bmCLoz66UYZ0mU,1427
239
- arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/user.py,sha256=-QxTreqrSZkIUDrTWkkTH8jI--tH7kXwpWq9TRn_1X4,1984
240
- arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/user_token.py,sha256=gGhpfqwydZ5VA6vdvNblp3NQHqXZLd1K3OxcYVU1SoM,1789
241
- arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/verification_code.py,sha256=_uuBUTkV7cAhHxaBVYk8JSp5voATOc-Kgq36-nC_o-w,2159
239
+ arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/story_log.py,sha256=INs2g2uy7CFlyVWUUXJOlEqawxNdWDdo00zy4Ly_RSM,1401
240
+ arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/user.py,sha256=npO1CSSycbgzgL7fWRuxIoB1zJySVqISP0ZKwjSm6y8,1953
241
+ arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/user_token.py,sha256=Q826LQIiK9J5JKKaAyB0xituMUxuMyyvFF-c1ekyAPM,1784
242
+ arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/model_view/verification_code.py,sha256=AU0f9VzBxeBkVTSp2tpqracLYW5gsJIx69PrIYTn5H8,2485
243
+ arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/start_sqladmin.py,sha256=g3kNKPR4X-PKpiSe4oFLHbZ-EJIwmWUOK6a5FABat_Y,375
242
244
  arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
243
245
  arpakitlib/_arpakit_project_template_v_5/project/sqladmin_/util/etc.py,sha256=jm65ZB0K8e6WpgcL2Y6pxcIuQjioIyMtBIOOFbbWfgk,1070
244
246
  arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -255,7 +257,7 @@ arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/sqlalchemy_model
255
257
  arpakitlib/_arpakit_project_template_v_5/project/sqlalchemy_db_/util.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
256
258
  arpakitlib/_arpakit_project_template_v_5/project/test_data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
257
259
  arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_api_keys.py,sha256=9F2bMfymaqx_Czh_tF945BKpKqNrVNjSIfCQl13Dkxw,911
258
- arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_1.py,sha256=kXtfNYVweDuv1z8gED2Zr1oP1NW5eMbeR3D7HGoguEE,1574
260
+ arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_1.py,sha256=B6due_6egjIT_tC5Glg2kIR0tBUNdlRW2Oyy6j-ga2Q,2212
259
261
  arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_2.py,sha256=VcCvxRLA0XnLaQcsaoZkIVV8rTO3uMyLTYoEsdxKtYE,416
260
262
  arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_3.py,sha256=9QJTgM4qsJXPgFhfVueQ9vObXr_dAldzP_p8dPO42uA,416
261
263
  arpakitlib/_arpakit_project_template_v_5/project/test_data/make_test_data_4.py,sha256=OyU9601WACF7cCpPT33x6CpizNJeQIPDDFezIvEO01A,416
@@ -340,9 +342,13 @@ arpakitlib/_arpakit_project_template_v_5/project/tg_bot/util/__init__.py,sha256=
340
342
  arpakitlib/_arpakit_project_template_v_5/project/tg_bot/util/etc.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
341
343
  arpakitlib/_arpakit_project_template_v_5/project/tg_bot/util/notify_admins.py,sha256=ikjp5J0qgq6LGxh6iFcVIKtO3cUed3p39NwcFLcatVE,2096
342
344
  arpakitlib/_arpakit_project_template_v_5/project/tg_bot/util/set_tg_bot_commands.py,sha256=eTVOpwp8zn74QhLgmbLkxn3cH4xPzQN02euS-7UP-Eg,3489
345
+ arpakitlib/_arpakit_project_template_v_5/project/tg_bot_notifier/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
346
+ arpakitlib/_arpakit_project_template_v_5/project/tg_bot_notifier/blank.py,sha256=0rspOC-xS9qdQ58pAJI-tNTgbylQIXCrEr79MMgvU1k,406
347
+ arpakitlib/_arpakit_project_template_v_5/project/tg_bot_notifier/tg_bot_notifier.py,sha256=9JbalZDmR4a2cqPe9rB_KnUX7YibVC6S5wTHma9G7AI,843
343
348
  arpakitlib/_arpakit_project_template_v_5/project/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
344
349
  arpakitlib/_arpakit_project_template_v_5/project/util/arpakitlib_project_template_util.py,sha256=syA_IuszHVub0zm0sVdB4_7rPJXwXRW4JmQ4qHbjXPk,396
345
350
  arpakitlib/_arpakit_project_template_v_5/project/util/etc.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
351
+ arpakitlib/_arpakit_project_template_v_5/project/util/send_email.py,sha256=lw-nUFtEYiGEChSZrfuXCtTkoY6fNT45M_Y6QfzOk90,2175
346
352
  arpakitlib/_arpakit_project_template_v_5/todo.txt,sha256=q132Jbx229ThY77S3YiN-Cj5AVm7k1VlJcMYIbZUHUY,3
347
353
  arpakitlib/ar_additional_model_util.py,sha256=GFg-glLCxH9X95R2bhTJsscVwv37FgE1qbaAAyXrnIE,917
348
354
  arpakitlib/ar_aiogram_util.py,sha256=4bizX5Xg-E2-r2TXXGQGanJozsIWPVf5luO3vKUN8p8,8471
@@ -392,8 +398,8 @@ arpakitlib/ar_ssh_runner_util.py,sha256=yvAwza480MkHKvLkDEsR7JNh2bYNs6P9rCVo4NA8
392
398
  arpakitlib/ar_str_util.py,sha256=CAv0wH8nP5Ja59S-hEdmNhNrM_Fwy935d0zntLpJkx8,4309
393
399
  arpakitlib/ar_type_util.py,sha256=Cs_tef-Fc5xeyAF54KgISCsP11NHyzIsglm4S3Xx7iM,4049
394
400
  arpakitlib/ar_yookassa_api_client_util.py,sha256=VozuZeCJjmLd1zj2BdC9WfiAQ3XYOrIMsdpNK-AUlm0,5347
395
- arpakitlib-1.8.111.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
396
- arpakitlib-1.8.111.dist-info/METADATA,sha256=Mjct-ehVPyOyZIp4nDKE5oJWtPvFcdJ_X2JmNcy45uI,3566
397
- arpakitlib-1.8.111.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
398
- arpakitlib-1.8.111.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
399
- arpakitlib-1.8.111.dist-info/RECORD,,
401
+ arpakitlib-1.8.113.dist-info/LICENSE,sha256=GPEDQMam2r7FSTYqM1mm7aKnxLaWcBotH7UvQtea-ec,11355
402
+ arpakitlib-1.8.113.dist-info/METADATA,sha256=UTCEQ0WcA44R7yM8uU_8vpU71CPbyK2VPE_--gwEYEY,3566
403
+ arpakitlib-1.8.113.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
404
+ arpakitlib-1.8.113.dist-info/entry_points.txt,sha256=36xqR3PJFT2kuwjkM_EqoIy0qFUDPKSm_mJaI7emewE,87
405
+ arpakitlib-1.8.113.dist-info/RECORD,,
@@ -1,37 +0,0 @@
1
- import logging
2
-
3
- from project.core.util import setup_logging
4
- from project.sqlalchemy_db_.sqlalchemy_db import get_cached_sqlalchemy_db
5
- from project.sqlalchemy_db_.sqlalchemy_model import UserDBM
6
-
7
- _logger = logging.getLogger(__name__)
8
-
9
-
10
- def create_first_admin():
11
- with get_cached_sqlalchemy_db().new_session() as session:
12
- user_dbm = (
13
- session
14
- .query(UserDBM)
15
- .filter(UserDBM.roles.any(UserDBM.Roles.admin))
16
- .first()
17
- )
18
- if user_dbm is not None:
19
- _logger.info("first admin already exists")
20
- return
21
- user_dbm = UserDBM(
22
- username="admin",
23
- roles=[UserDBM.Roles.client, UserDBM.Roles.admin],
24
- password="admin",
25
- )
26
- session.add(user_dbm)
27
- session.commit()
28
- _logger.info("first admin was created")
29
-
30
-
31
- def command():
32
- setup_logging()
33
- create_first_admin()
34
-
35
-
36
- if __name__ == '__main__':
37
- command()