diff --git a/back/add_poems_and_filters.py b/back/add_poems_and_filters.py index 6c6116f..cdeee8a 100644 --- a/back/add_poems_and_filters.py +++ b/back/add_poems_and_filters.py @@ -43,7 +43,7 @@ def add_poems_to_db(db: Session): f1.close() -def filter_ann(schema: pydantic_schemas.SortAnnouncements, db: Annotated[Session, Depends(auth_utils.get_db)]): +def filter_ann(schema: pydantic_schemas.SortAnnouncements, db: Annotated[Session, Depends(auth_utils.get_session)]): """Функция для последовательного применения различных фильтров (через схему SortAnnouncements)""" res = db.query(orm_models.Announcement) fields = schema.__dict__ # параметры передоваемой схемы SortAnnouncements (ключи и значения) @@ -58,7 +58,7 @@ def filter_ann(schema: pydantic_schemas.SortAnnouncements, db: Annotated[Session return res.all() -def check_obsolete(db: Annotated[Session, Depends(auth_utils.get_db)], current_date: datetime.date): +def check_obsolete(db: Annotated[Session, Depends(auth_utils.get_session)], current_date: datetime.date): """ Функция участвует в процессе обновления поля obsolete у всех объявлений раз в сутки """ diff --git a/back/api.py b/back/api.py index 177373d..9fa745b 100644 --- a/back/api.py +++ b/back/api.py @@ -22,7 +22,6 @@ import pathlib import shutil import os -from .db import database from . import add_poems_and_filters, auth_utils, orm_models, pydantic_schemas # создаем приложение Fastapi @@ -31,6 +30,9 @@ app = FastAPI() # Jinja2 - шаблоны templates = Jinja2Templates(directory="./front/dist") + +# хранение картинок для стихов +app.mount("/poem_pic", StaticFiles(directory = "./poem_pic")) # создаем эндпоинт для хранения статических файлов app.mount("/static", StaticFiles(directory = "./front/dist")) # проверяем, что папка uploads еще не создана @@ -42,7 +44,7 @@ app.mount("/uploads", StaticFiles(directory = "./uploads")) # получение списка объявлений @app.get("/api/announcements", response_model=List[pydantic_schemas.Announcement])#адрес объявлений -def announcements_list(db: Annotated[Session, Depends(auth_utils.get_db)], obsolete: Union[bool, None] = False, user_id: Union[int, None] = None, +async def announcements_list(db: Annotated[Session, Depends(auth_utils.get_session)], obsolete: Union[bool, None] = False, user_id: Union[int, None] = None, metro: Union[str, None] = None,category: Union[str, None] = None): # параметры для сортировки (схема pydantic schemas.SortAnnouncements) params_to_sort = pydantic_schemas.SortAnnouncements(obsolete=obsolete, user_id=user_id, metro=metro, category=category) @@ -54,7 +56,7 @@ def announcements_list(db: Annotated[Session, Depends(auth_utils.get_db)], obsol # получаем данные одного объявления @app.get("/api/announcement", response_model=pydantic_schemas.AnnResponce) -def single_announcement(ann_id:int, db: Annotated[Session, Depends(auth_utils.get_db)]): # передаем индекс обявления +async def single_announcement(ann_id:int, db: Annotated[Session, Depends(auth_utils.get_session)]): # передаем индекс обявления # Считываем данные из Body и отображаем их на странице. # В последствии будем вставлять данные в html-форму try: @@ -66,10 +68,10 @@ def single_announcement(ann_id:int, db: Annotated[Session, Depends(auth_utils.ge # Занести объявление в базу данных @app.put("/api/announcement") -def put_in_db(name: Annotated[str, Form()], category: Annotated[str, Form()], bestBy: Annotated[datetime.date, Form()], +async def put_in_db(name: Annotated[str, Form()], category: Annotated[str, Form()], bestBy: Annotated[datetime.date, Form()], address: Annotated[str, Form()], longtitude: Annotated[float, Form()], latitude: Annotated[float, Form()], description: Annotated[str, Form()], metro: Annotated[str, Form()], current_user: Annotated[pydantic_schemas.User, Depends(auth_utils.get_current_active_user)], - db: Annotated[Session, Depends(auth_utils.get_db)], src: Union[UploadFile, None] = None, trashId: Annotated[int, Form()] = None): + db: Annotated[Session, Depends(auth_utils.get_session)], src: Union[UploadFile, None] = None, trashId: Annotated[int, Form()] = None): try: # имя загруженного файла по умолчанию - пустая строка uploaded_name = "" @@ -101,7 +103,7 @@ def put_in_db(name: Annotated[str, Form()], category: Annotated[str, Form()], be # Удалить объявления из базы @app.delete("/api/announcement") #адрес объявления -def delete_from_db(announcement: pydantic_schemas.DelAnnouncement, db: Annotated[Session, Depends(auth_utils.get_db)]): # функция удаления объекта из БД +async def delete_from_db(announcement: pydantic_schemas.DelAnnouncement, db: Annotated[Session, Depends(auth_utils.get_session)]): # функция удаления объекта из БД try: # находим объект с заданным id в бд to_delete = db.query(orm_models.Announcement).filter(orm_models.Announcement.id==announcement.id).first() @@ -114,8 +116,8 @@ def delete_from_db(announcement: pydantic_schemas.DelAnnouncement, db: Annotated # Забронировать объявление @app.post("/api/book") -def change_book_status(data: pydantic_schemas.Book, current_user: Annotated[pydantic_schemas.User, Depends(auth_utils.get_current_user)], - db: Annotated[Session, Depends(auth_utils.get_db)]): +async def change_book_status(data: pydantic_schemas.Book, current_user: Annotated[pydantic_schemas.User, Depends(auth_utils.get_current_user)], + db: Annotated[Session, Depends(auth_utils.get_session)]): # Находим объявление по данному id announcement_to_change = db.query(orm_models.Announcement).filter(orm_models.Announcement.id == data.id).first() # Проверяем, что объявление с данным id существует @@ -135,7 +137,7 @@ def change_book_status(data: pydantic_schemas.Book, current_user: Annotated[pyda # reginstration @app.post("/api/signup") -def create_user(nickname: Annotated[str, Form()], password: Annotated[str, Form()], db: Annotated[Session, Depends(auth_utils.get_db)], +async def create_user(nickname: Annotated[str, Form()], password: Annotated[str, Form()], db: Annotated[Session, Depends(auth_utils.get_session)], name: Annotated[str, Form()]=None, surname: Annotated[str, Form()]=None, avatar: Annotated[UploadFile, Form()]=None): # проверяем, что юзера с введенным никнеймом не существует в бд @@ -154,7 +156,7 @@ def create_user(nickname: Annotated[str, Form()], password: Annotated[str, Form( # функция для генерации токена после успешного входа пользователя @app.post("/api/token", response_model=pydantic_schemas.Token) async def login_for_access_token( - form_data: Annotated[OAuth2PasswordRequestForm, Depends()], db: Annotated[Session, Depends(auth_utils.get_db)] + form_data: Annotated[OAuth2PasswordRequestForm, Depends()], db: Annotated[Session, Depends(auth_utils.get_session)] ): # пробуем найти юзера в бд по введенным паролю и никнейму user = auth_utils.authenticate_user(db, form_data.username, form_data.password) @@ -182,7 +184,7 @@ async def read_users_me(current_user: Annotated[pydantic_schemas.User, Depends(a # изменяем рейтинг пользователя @app.post("/api/user/rating") -def add_points(data: pydantic_schemas.AddRating, current_user: Annotated[pydantic_schemas.User, Depends(auth_utils.get_current_user)], db: Annotated[Session, Depends(auth_utils.get_db)]): +async def add_points(data: pydantic_schemas.AddRating, current_user: Annotated[pydantic_schemas.User, Depends(auth_utils.get_current_user)], db: Annotated[Session, Depends(auth_utils.get_session)]): # проверяем, if current_user.id != data.user_id: user = auth_utils.get_user_by_id(db, data.user_id) @@ -197,7 +199,7 @@ def add_points(data: pydantic_schemas.AddRating, current_user: Annotated[pydanti # получаем рейтинг пользователя @app.get("/api/user/rating") -def add_points(user_id: int, db: Annotated[Session, Depends(auth_utils.get_db)]): +async def add_points(user_id: int, db: Annotated[Session, Depends(auth_utils.get_session)]): user = auth_utils.get_user_by_id(db, user_id=user_id) if not user: raise HTTPException(status_code=404, detail="Item not found") @@ -205,11 +207,13 @@ def add_points(user_id: int, db: Annotated[Session, Depends(auth_utils.get_db)]) # Отправляем стихи -@app.get("/api/user/poem", response_model=pydantic_schemas.Poem) # пока не работает -def poems_to_front(db: Annotated[Session, Depends(auth_utils.get_db)]): # db: Annotated[Session, Depends(utils.get_db)] +@app.get("/api/user/poem", response_model=pydantic_schemas.Poem) +async def poems_to_front(db: Annotated[Session, Depends(auth_utils.get_session)]): num_of_poems = db.query(orm_models.Poems).count() # определяем кол-во стихов в бд + # если стихов в бд нет if num_of_poems < 1: - add_poems_and_filters.add_poems_to_db(database) # добавляем поэмы в базу данных + add_poems_and_filters.add_poems_to_db(db) # добавляем поэмы в базу данных + num_of_poems = db.query(orm_models.Poems).count() # определяем кол-во стихов в бд rand_id = random.randint(1, num_of_poems) # генерируем номер стихотворения poem = db.query(orm_models.Poems).filter(orm_models.Poems.id == rand_id).first() # находим стих в бд if not poem: @@ -218,7 +222,7 @@ def poems_to_front(db: Annotated[Session, Depends(auth_utils.get_db)]): # db: An @app.get("/api/trashbox", response_model=List[pydantic_schemas.TrashboxResponse]) -def get_trashboxes(data: pydantic_schemas.TrashboxRequest = Depends()):#крутая функция для работы с api +async def get_trashboxes(data: pydantic_schemas.TrashboxRequest = Depends()):#крутая функция для работы с api # json, передаваемый стороннему API BASE_URL= "https://geointelect2.gate.petersburg.ru" my_token="eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJhU1RaZm42bHpTdURYcUttRkg1SzN5UDFhT0FxUkhTNm9OendMUExaTXhFIn0.eyJleHAiOjE3ODYyMjUzMzMsImlhdCI6MTY5MTUzMDkzMywianRpIjoiYjU0MmU3MTQtYzJkMS00NTY2LWJkY2MtYmQ5NzA0ODY1ZjgzIiwiaXNzIjoiaHR0cHM6Ly9rYy5wZXRlcnNidXJnLnJ1L3JlYWxtcy9lZ3MtYXBpIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImJjYjQ2NzljLTU3ZGItNDU5ZC1iNWUxLWRlOGI4Yzg5MTMwMyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFkbWluLXJlc3QtY2xpZW50Iiwic2Vzc2lvbl9zdGF0ZSI6IjJhOTgwMzUyLTY1M2QtNGZlZC1iMDI1LWQ1N2U0NDRjZmM3NiIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiLyoiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZWdzLWFwaSIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiIyYTk4MDM1Mi02NTNkLTRmZWQtYjAyNS1kNTdlNDQ0Y2ZjNzYiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiLQktC70LDQtNC40LzQuNGAINCv0LrQvtCy0LvQtdCyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiZTBmYzc2OGRhOTA4MjNiODgwZGQzOGVhMDJjMmQ5NTciLCJnaXZlbl9uYW1lIjoi0JLQu9Cw0LTQuNC80LjRgCIsImZhbWlseV9uYW1lIjoi0K_QutC-0LLQu9C10LIifQ.FTKiC1hpWcOkmSW9QZpC-RY7Ko50jw1mDMfXIWYxlQ-zehLm2CLmOnHvYoOoI39k2OzeCIAB9ZdRrrGZc6G9Z1eFELUjNGEqKxSC1Phj9ATemKgbOKEttk-OGc-rFr9VPA8_SnfvLts6wTI2YK33YBIxCF5nCbnr4Qj3LeEQ0d6Hy8PO4ATrBF5EOeuAZRprvIEjXe_f8N9ONKckCPB-xFB4P2pZlVXGoCNoewGEcY3zXH4khezN6zcVr6tpc6G8dBv9EqT_v92IDSg-aXQk6ysA0cO0-6x5w1-_qU0iHGIAPsLNV9IKBoFbjc0JH6cWabldPRH12NP1trvYfqKDGQ" @@ -277,8 +281,8 @@ async def react_app(req: Request, rest_of_path: str): @app.post("/api/announcement/dispose") -def dispose(data: pydantic_schemas.DisposeRequest, current_user_schema: Annotated[pydantic_schemas.User, Depends(auth_utils.get_current_user)], - db: Annotated[Session, Depends(auth_utils.get_db)]): +async def dispose(data: pydantic_schemas.DisposeRequest, current_user_schema: Annotated[pydantic_schemas.User, Depends(auth_utils.get_current_user)], + db: Annotated[Session, Depends(auth_utils.get_session)]): # Находим в бд текущего юзера current_user = auth_utils.get_user_by_id(db, current_user_schema.id) # Начисляем баллы пользователю за утилизацию diff --git a/back/auth_utils.py b/back/auth_utils.py index 594627c..bf5d95e 100644 --- a/back/auth_utils.py +++ b/back/auth_utils.py @@ -1,54 +1,55 @@ from datetime import datetime, timedelta from typing import Annotated, Union +import os from fastapi import Depends, HTTPException, status from fastapi.security import OAuth2PasswordBearer from jose import JWTError, jwt from passlib.context import CryptContext +from sqlalchemy import select from sqlalchemy.orm import Session +from sqlalchemy.ext.asyncio import AsyncSession +from dotenv import load_dotenv -from .db import database +from .db import SessionLocal from . import orm_models, pydantic_schemas - -SECRET_KEY = "651a52941cf5de14d48ef5d7af115709" -ALGORITHM = "HS256" -ACCESS_TOKEN_EXPIRE_MINUTES = 1440 +load_dotenv("unimportant.env") +SECRET_KEY = os.getenv("SECRET_KEY") +ALGORITHM = os.getenv("ALGORITHM") +ACCESS_TOKEN_EXPIRE_MINUTES = os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES") pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/token") -def get_db(): - db = database - try: - yield db - finally: - db.close() +async def get_session() -> AsyncSession: + async with SessionLocal() as session: + yield session -def verify_password(plain_password, hashed_password): +async def verify_password(plain_password, hashed_password): return pwd_context.verify(plain_password, hashed_password) -def get_password_hash(password): +async def get_password_hash(password): return pwd_context.hash(password) -def get_user_by_nickname(db: Annotated[Session, Depends(get_db)], nickname: str): - user_with_required_id = db.query(orm_models.User).filter(orm_models.User.nickname == nickname).first() +async def get_user_by_nickname(db: Annotated[AsyncSession, Depends(get_session)], nickname: str): + user_with_required_id = db.select(orm_models.User).where(orm_models.User.nickname == nickname).first() if user_with_required_id: return user_with_required_id return None -def get_user_by_id(db: Annotated[Session, Depends(get_db)], user_id: int): - user_with_required_id = db.query(orm_models.User).filter(orm_models.User.id == user_id).first() +async def get_user_by_id(db: Annotated[AsyncSession, Depends(get_session)], user_id: int): + user_with_required_id = db.select(orm_models.User).where(orm_models.User.id == user_id).first() if user_with_required_id: return user_with_required_id return None -def authenticate_user(db: Annotated[Session, Depends(get_db)], nickname: str, password: str): +async def authenticate_user(db: Annotated[AsyncSession, Depends(get_session)], nickname: str, password: str): user = get_user_by_nickname(db=db, nickname=nickname) if not user: return False @@ -57,7 +58,7 @@ def authenticate_user(db: Annotated[Session, Depends(get_db)], nickname: str, pa return user -def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None): +async def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None): to_encode = data.copy() if expires_delta: expire = datetime.utcnow() + expires_delta @@ -68,7 +69,7 @@ def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None return encoded_jwt -async def get_current_user(db: Annotated[Session, Depends(get_db)], token: Annotated[str, Depends(oauth2_scheme)]): +async def get_current_user(db: Annotated[AsyncSession, Depends(get_session)], token: Annotated[str, Depends(oauth2_scheme)]): credentials_exception = HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Could not validate credentials", diff --git a/back/db.py b/back/db.py index 12d83a7..a2a3b41 100644 --- a/back/db.py +++ b/back/db.py @@ -1,32 +1,21 @@ -from typing import AsyncGenerator - -from sqlalchemy import create_engine, MetaData -# from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine -from sqlalchemy.orm import sessionmaker, DeclarativeBase +from asyncio import current_task +from sqlalchemy.ext.asyncio import AsyncSession, async_scoped_session, create_async_engine +from sqlalchemy.orm import sessionmaker from sqlalchemy.ext.declarative import declarative_base -SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db" +SQLALCHEMY_DATABASE_URL = 'postgresql+asyncpg://postgres:D560c34V112Ak@localhost/porridger' -engine = create_engine( - SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} -) +engine = create_async_engine(SQLALCHEMY_DATABASE_URL, echo=True) -SessionLocal = sessionmaker(bind=engine, autoflush=True, autocommit=False) +SessionLocal = sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False) -database = SessionLocal() +async_session = async_scoped_session(SessionLocal, scopefunc=current_task) Base = declarative_base() -# # add your model's MetaData object here -# # for 'autogenerate' support -# # in your application's model: - -# class Base(DeclarativeBase): -# metadata = MetaData(naming_convention={ -# "ix": "ix_%(column_0_label)s", -# "uq": "uq_%(table_name)s_%(column_0_name)s", -# "ck": "ck_%(table_name)s_`%(constraint_name)s`", -# "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s", -# "pk": "pk_%(table_name)s" -# }) \ No newline at end of file +# Создаем таблицы +async def init_models(): + async with engine.begin() as conn: + await conn.run_sync(Base.metadata.drop_all) + await conn.run_sync(Base.metadata.create_all) \ No newline at end of file diff --git a/back/delete_db.py b/back/delete_db.py new file mode 100644 index 0000000..5b22d85 --- /dev/null +++ b/back/delete_db.py @@ -0,0 +1,6 @@ +from sqlalchemy import Table, MetaData, text +from .db import engine, Base + +tbl = Table('Poems', MetaData(), autoload_with=engine) +tbl.drop(engine, checkfirst=False) +a = input() diff --git a/back/orm_models.py b/back/orm_models.py index 1e807f9..c866d6f 100644 --- a/back/orm_models.py +++ b/back/orm_models.py @@ -66,24 +66,3 @@ class Poems(Base):#класс поэзии author = Column(String) # автор стихотворения -# Создаем описанные выше таблицы -Base.metadata.create_all(bind=engine) - - - -# from typing import AsyncGenerator -# from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine -# from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase -# # This function can be called during the initialization of the FastAPI app. -# async def create_db_and_tables(): -# async with engine.begin() as conn: -# await conn.run_sync(Base.metadata.create_all) - - -# async def get_async_session() -> AsyncGenerator[AsyncSession, None]: -# async with async_session_maker() as session: -# yield session - - -# async def get_user_db(session: AsyncSession = Depends(get_async_session)): -# yield SQLAlchemyUserDatabase(session, User) \ No newline at end of file diff --git a/back/scheduler.py b/back/scheduler.py index deb1b92..0ec340d 100644 --- a/back/scheduler.py +++ b/back/scheduler.py @@ -7,7 +7,7 @@ from .db import database app = Rocketry(execution="async") # Create task: -@app.task('daily') +@app.task('minutely') async def daily_check(): # Фильтруем по сроку годности add_poems_and_filters.check_obsolete(database, current_date=datetime.date.today()) diff --git a/back/unimportant.env b/back/unimportant.env index 3e418f7..419962b 100644 --- a/back/unimportant.env +++ b/back/unimportant.env @@ -1,2 +1,5 @@ TOKEN = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJhU1RaZm42bHpTdURYcUttRkg1SzN5UDFhT0FxUkhTNm9OendMUExaTXhFIn0.eyJleHAiOjE3ODYyMjUzMzMsImlhdCI6MTY5MTUzMDkzMywianRpIjoiYjU0MmU3MTQtYzJkMS00NTY2LWJkY2MtYmQ5NzA0ODY1ZjgzIiwiaXNzIjoiaHR0cHM6Ly9rYy5wZXRlcnNidXJnLnJ1L3JlYWxtcy9lZ3MtYXBpIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImJjYjQ2NzljLTU3ZGItNDU5ZC1iNWUxLWRlOGI4Yzg5MTMwMyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFkbWluLXJlc3QtY2xpZW50Iiwic2Vzc2lvbl9zdGF0ZSI6IjJhOTgwMzUyLTY1M2QtNGZlZC1iMDI1LWQ1N2U0NDRjZmM3NiIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiLyoiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZWdzLWFwaSIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiIyYTk4MDM1Mi02NTNkLTRmZWQtYjAyNS1kNTdlNDQ0Y2ZjNzYiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiLQktC70LDQtNC40LzQuNGAINCv0LrQvtCy0LvQtdCyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiZTBmYzc2OGRhOTA4MjNiODgwZGQzOGVhMDJjMmQ5NTciLCJnaXZlbl9uYW1lIjoi0JLQu9Cw0LTQuNC80LjRgCIsImZhbWlseV9uYW1lIjoi0K_QutC-0LLQu9C10LIifQ.FTKiC1hpWcOkmSW9QZpC-RY7Ko50jw1mDMfXIWYxlQ-zehLm2CLmOnHvYoOoI39k2OzeCIAB9ZdRrrGZc6G9Z1eFELUjNGEqKxSC1Phj9ATemKgbOKEttk-OGc-rFr9VPA8_SnfvLts6wTI2YK33YBIxCF5nCbnr4Qj3LeEQ0d6Hy8PO4ATrBF5EOeuAZRprvIEjXe_f8N9ONKckCPB-xFB4P2pZlVXGoCNoewGEcY3zXH4khezN6zcVr6tpc6G8dBv9EqT_v92IDSg-aXQk6ysA0cO0-6x5w1-_qU0iHGIAPsLNV9IKBoFbjc0JH6cWabldPRH12NP1trvYfqKDGQ" -DOMAIN = "https://geointelect2.gate.petersburg.ru" \ No newline at end of file +DOMAIN = "https://geointelect2.gate.petersburg.ru" +SECRET_KEY = "651a52941cf5de14d48ef5d7af115709" +ALGORITHM = "HS256" +ACCESS_TOKEN_EXPIRE_MINUTES = 1440 \ No newline at end of file