Compare commits

...

3 Commits

5 changed files with 312 additions and 63 deletions

View File

@ -1,6 +1,13 @@
from sqlalchemy import create_engine from typing import AsyncGenerator
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String, create_engine, select
# from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import sessionmaker, Session from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.ext.declarative import declarative_base
from fastapi import Depends
# from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db" SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
@ -8,6 +15,7 @@ engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
) )
SessionLocal = sessionmaker(autoflush=True, bind=engine) SessionLocal = sessionmaker(bind=engine, expire_on_commit=False)
database = SessionLocal()
Base = declarative_base() Base = declarative_base()

View File

@ -1,3 +1,7 @@
<<<<<<< HEAD
# <<<<<<< HEAD
=======
>>>>>>> de8a1abcbfea61d8d4898c18e133b8b0feaf87e8
#подключение библиотек #подключение библиотек
from fastapi import FastAPI, Response, Path, Depends, Body, Form, Query, status, HTTPException, APIRouter, UploadFile, File from fastapi import FastAPI, Response, Path, Depends, Body, Form, Query, status, HTTPException, APIRouter, UploadFile, File
from fastapi.responses import HTMLResponse, FileResponse, JSONResponse, RedirectResponse from fastapi.responses import HTMLResponse, FileResponse, JSONResponse, RedirectResponse
@ -19,21 +23,20 @@ import shutil
import os import os
from .utils import * from .utils import *
from .models import Announcement, Trashbox, UserDatabase, Base from .db import Base, engine, SessionLocal, database
from .db import engine, SessionLocal from .models import Announcement, Trashbox, UserDatabase
from . import schema from . import schema
Base.metadata.create_all(bind=engine) Base.metadata.create_all(bind=engine)
db = SessionLocal()
app = FastAPI() app = FastAPI()
templates = Jinja2Templates(directory="./front/dist") templates = Jinja2Templates(directory="./front/dist")
app.mount("/static", StaticFiles(directory = "./front/dist")) app.mount("/static", StaticFiles(directory = "./front/dist"))
if not os.path.exists("./uploads"):
os.mkdir("C:/Users/38812/porridger/uploads")
app.mount("/uploads", StaticFiles(directory = "./uploads")) app.mount("/uploads", StaticFiles(directory = "./uploads"))
@ -42,11 +45,11 @@ def annoncements_list(user_id: int = None, metro: str = None, category: str = No
# Считываем данные из Body и отображаем их на странице. # Считываем данные из Body и отображаем их на странице.
# В последствии будем вставлять данные в html-форму # В последствии будем вставлять данные в html-форму
a = db.query(Announcement) a = database.query(Announcement)
b = db.query(Announcement) b = database.query(Announcement)
c = db.query(Announcement) c = database.query(Announcement)
d = db.query(Announcement) d = database.query(Announcement)
e = db.query(Announcement) e = database.query(Announcement)
if user_id != None: if user_id != None:
b = a.filter(Announcement.user_id == user_id) b = a.filter(Announcement.user_id == user_id)
@ -74,7 +77,7 @@ def single_annoncement(user_id:int):
# Считываем данные из Body и отображаем их на странице. # Считываем данные из Body и отображаем их на странице.
# В последствии будем вставлять данные в html-форму # В последствии будем вставлять данные в html-форму
try: try:
annoncement = db.get(Announcement, user_id) annoncement = database.get(Announcement, user_id)
return {"id": annoncement.id, "user_id": annoncement.user_id, "name": annoncement.name, return {"id": annoncement.id, "user_id": annoncement.user_id, "name": annoncement.name,
"category": annoncement.category, "best_by": annoncement.best_by, "address": annoncement.address, "category": annoncement.category, "best_by": annoncement.best_by, "address": annoncement.address,
"description": annoncement.description, "metro": annoncement.metro, "latitude": annoncement.latitude, "description": annoncement.description, "metro": annoncement.metro, "latitude": annoncement.latitude,
@ -115,8 +118,8 @@ def put_in_db(name: Annotated[str, Form()], category: Annotated[str, Form()], be
@app.delete("/api/announcement") #адрес объявления @app.delete("/api/announcement") #адрес объявления
def delete_from_db(data = Body()):#функция удаления объекта из БД def delete_from_db(data = Body()):#функция удаления объекта из БД
try: try:
db.delete(user_id=data.user_id)#удаление из БД database.delete(user_id=data.user_id)#удаление из БД
db.commit() # сохраняем изменения database.commit() # сохраняем изменения
return {"Answer" : True} return {"Answer" : True}
except: except:
return {"Answer" : False} return {"Answer" : False}
@ -129,21 +132,21 @@ def change_book_status(data: schema.Book):
# Получаем id пользователя, который бронирует объявление # Получаем id пользователя, который бронирует объявление
temp_user_id = 1 temp_user_id = 1
# Находим объявление по данному id # Находим объявление по данному id
announcement_to_change = db.query(Announcement).filter(id == data.id).first() announcement_to_change = database.query(Announcement).filter(id == data.id).first()
# Изменяем поле booked_status на полученный id # Изменяем поле booked_status на полученный id
announcement_to_change.booked_status = temp_user_id announcement_to_change.booked_status = temp_user_id
return {"Success": True} return {"Success": True}
except: except:
return {"Success": False} return {"Success": False}
# reginstration
@app.post("/api/signup") @app.post("/api/signup")
def create_user(data = Body()): def create_user(data = Body()):
if db.query(UserDatabase).filter(UserDatabase.email == data["email"]).first() == None: if database.query(UserDatabase).filter(UserDatabase.email == data["email"]).first() == None:
new_user = UserDatabase(id=data["id"], email=data["email"], password=data["password"], name=data["name"], surname=data["surname"]) new_user = UserDatabase(id=data["id"], email=data["email"], password=data["password"], name=data["name"], surname=data["surname"])
db.add(new_user) database.add(new_user)
db.commit() database.commit()
db.refresh(new_user) # обновляем состояние объекта database.refresh(new_user) # обновляем состояние объекта
return {"Success": True} return {"Success": True}
return {"Success": False, "Message": "Пользователь с таким email уже зарегестрирован."} return {"Success": False, "Message": "Пользователь с таким email уже зарегестрирован."}
@ -153,7 +156,7 @@ async def login_for_access_token(
form_data: Annotated[OAuth2PasswordRequestForm, Depends()] form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
): ):
# разобраться с первым параметром # разобраться с первым параметром
user = authenticate_user(db.query(UserDatabase).all(), form_data.username, form_data.password) user = authenticate_user(database, form_data.username, form_data.password)
if not user: if not user:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
@ -217,3 +220,226 @@ def get_trashboxes(lat:float, lng:float):#крутая функция для р
@app.get("/{rest_of_path:path}") @app.get("/{rest_of_path:path}")
async def react_app(req: Request, rest_of_path: str): async def react_app(req: Request, rest_of_path: str):
return templates.TemplateResponse('index.html', { 'request': req }) return templates.TemplateResponse('index.html', { 'request': req })
<<<<<<< HEAD
# =======
# #подключение библиотек
# from fastapi import FastAPI, Response, Path, Depends, Body, Form, Query, status, HTTPException, APIRouter, UploadFile, File
# from fastapi.responses import HTMLResponse, FileResponse, JSONResponse, RedirectResponse
# from fastapi.staticfiles import StaticFiles
# from fastapi.security import OAuth2PasswordRequestForm, OAuth2PasswordBearer
# from fastapi.templating import Jinja2Templates
# from fastapi.requests import Request
# from pydantic import json
# from starlette.staticfiles import StaticFiles
# import requests
# from uuid import uuid4
# import ast
# import pathlib
# import shutil
# import os
# from .utils import *
# from .models import Announcement, Trashbox, UserDatabase, Base
# from .db import engine, SessionLocal
# from . import schema
# Base.metadata.create_all(bind=engine)
# db = SessionLocal()
# app = FastAPI()
# templates = Jinja2Templates(directory="./front/dist")
# app.mount("/static", StaticFiles(directory = "./front/dist"))
# app.mount("/uploads", StaticFiles(directory = "./uploads"))
# @app.get("/api/announcements")#адрес объявлений
# def annoncements_list(user_id: int = None, metro: str = None, category: str = None, booked_by: int = -1):
# # Считываем данные из Body и отображаем их на странице.
# # В последствии будем вставлять данные в html-форму
# a = db.query(Announcement)
# b = db.query(Announcement)
# c = db.query(Announcement)
# d = db.query(Announcement)
# e = db.query(Announcement)
# if user_id != None:
# b = a.filter(Announcement.user_id == user_id)
# if metro != None:
# c = a.filter(Announcement.metro == metro)
# if category != None:
# d = a.filter(Announcement.category == category)
# if booked_by != -1:
# e = a.filter(Announcement.booked_by == booked_by)
# if not any([category, user_id, metro]) and booked_by == -1:
# result = a.all()
# else:
# result = b.intersect(c, d, e).all()
# return {"Success" : True, "list_of_announcements": result}
# @app.get("/api/announcement")#адрес объявлений
# def single_annoncement(user_id:int):
# # Считываем данные из Body и отображаем их на странице.
# # В последствии будем вставлять данные в html-форму
# try:
# annoncement = db.get(Announcement, user_id)
# return {"id": annoncement.id, "user_id": annoncement.user_id, "name": annoncement.name,
# "category": annoncement.category, "best_by": annoncement.best_by, "address": annoncement.address,
# "description": annoncement.description, "metro": annoncement.metro, "latitude": annoncement.latitude,
# "longtitude":annoncement.longtitude, "trashId": annoncement.trashId, "src":annoncement.src,
# "booked_by":annoncement.booked_by}
# except:
# return {"Answer" : False} #если неуданый доступ, то сообщаем об этом
# # Занести объявление в базу
# @app.put("/api/announcement")#адрес объявлений
# def put_in_db(name: Annotated[str, Form()], category: Annotated[str, Form()], bestBy: Annotated[int, Form()], address: Annotated[str, Form()], longtitude: Annotated[float, Form()], latitude: Annotated[float, Form()], description: Annotated[str, Form()], src: Annotated[UploadFile | None, File()], metro: Annotated[str, Form()], trashId: Annotated[int | None, Form()] = -1):
# # try:
# userId = 1 # temporary
# uploaded_name = ""
# f = src.file
# f.seek(0, os.SEEK_END)
# if f.tell() > 0:
# f.seek(0)
# destination = pathlib.Path("./uploads/" + str(hash(src.file)) + pathlib.Path(src.filename).suffix.lower())
# with destination.open('wb') as buffer:
# shutil.copyfileobj(src.file, buffer)
# uploaded_name = "/uploads/"+destination.name
# temp_ancmt = Announcement(user_id=userId, name=name, category=category, best_by=bestBy, address=address, longtitude=longtitude, latitude=latitude, description=description, src=uploaded_name, metro=metro, trashId=trashId, booked_by=-1)
# db.add(temp_ancmt) # добавляем в бд
# db.commit() # сохраняем изменения
# db.refresh(temp_ancmt) # обновляем состояние объекта
# return {"Answer" : True}
# # except:
# # return {"Answer" : False}
# # Удалить объявления из базы
# @app.delete("/api/announcement") #адрес объявления
# def delete_from_db(data = Body()):#функция удаления объекта из БД
# try:
# db.delete(user_id=data.user_id)#удаление из БД
# db.commit() # сохраняем изменения
# return {"Answer" : True}
# except:
# return {"Answer" : False}
# # Забронировать объявление
# @app.post("/api/book")
# def change_book_status(data: schema.Book):
# try:
# # Получаем id пользователя, который бронирует объявление
# temp_user_id = 1
# # Находим объявление по данному id
# announcement_to_change = db.query(Announcement).filter(id == data.id).first()
# # Изменяем поле booked_status на полученный id
# announcement_to_change.booked_status = temp_user_id
# return {"Success": True}
# except:
# return {"Success": False}
# @app.post("/api/signup")
# def create_user(data = Body()):
# if db.query(UserDatabase).filter(User.email == data["email"]).first() == None:
# new_user = UserDatabase(id=data["id"], email=data["email"], password=data["password"], name=data["name"], surname=data["surname"])
# db.add(new_user)
# db.commit()
# db.refresh(new_user) # обновляем состояние объекта
# return {"Success": True}
# return {"Success": False, "Message": "Пользователь с таким email уже зарегестрирован."}
# @app.post("/api/token", response_model=Token)
# async def login_for_access_token(
# form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
# ):
# user = authenticate_user(db.query(UserDatabase).all(), form_data.username, form_data.password)
# if not user:
# raise HTTPException(
# status_code=status.HTTP_401_UNAUTHORIZED,
# detail="Incorrect username or password",
# headers={"WWW-Authenticate": "Bearer"},
# )
# access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
# access_token = create_access_token(
# data={"user_id": user.id}, expires_delta=access_token_expires
# )
# return {"access_token": access_token, "token_type": "bearer"}
# @app.get("/api/users/me/", response_model=User)
# async def read_users_me(
# current_user: Annotated[User, Depends(get_current_active_user)]
# ):
# return current_user
# @app.get("/api/users/me/items/")
# async def read_own_items(
# current_user: Annotated[User, Depends(get_current_active_user)]
# ):
# return [{"Current user name": current_user.name, "Current user surname": current_user.surname}]
# @app.get("/api/trashbox")
# def get_trashboxes(lat:float, lng:float):#крутая функция для работы с api
# BASE_URL='https://geointelect2.gate.petersburg.ru'#адрес сайта и мой токин
# my_token='eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJhU1RaZm42bHpTdURYcUttRkg1SzN5UDFhT0FxUkhTNm9OendMUExaTXhFIn0.eyJleHAiOjE3Nzg2NTk4MjEsImlhdCI6MTY4Mzk2NTQyMSwianRpIjoiOTI2ZGMyNmEtMGYyZi00OTZiLWI0NTUtMWQyYWM5YmRlMTZkIiwiaXNzIjoiaHR0cHM6Ly9rYy5wZXRlcnNidXJnLnJ1L3JlYWxtcy9lZ3MtYXBpIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImJjYjQ2NzljLTU3ZGItNDU5ZC1iNWUxLWRlOGI4Yzg5MTMwMyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImFkbWluLXJlc3QtY2xpZW50Iiwic2Vzc2lvbl9zdGF0ZSI6IjE2MGU1ZGVkLWFmMjMtNDkyNS05OTc1LTRhMzM0ZjVmNTkyOSIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiLyoiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImRlZmF1bHQtcm9sZXMtZWdzLWFwaSIsIm9mZmxpbmVfYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJzaWQiOiIxNjBlNWRlZC1hZjIzLTQ5MjUtOTk3NS00YTMzNGY1ZjU5MjkiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiLQktC70LDQtNC40LzQuNGAINCv0LrQvtCy0LvQtdCyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiZTBmYzc2OGRhOTA4MjNiODgwZGQzOGVhMDJjMmQ5NTciLCJnaXZlbl9uYW1lIjoi0JLQu9Cw0LTQuNC80LjRgCIsImZhbWlseV9uYW1lIjoi0K_QutC-0LLQu9C10LIifQ.BRyUIyY-KKnZ9xqTNa9vIsfKF0UN2VoA9h4NN4y7IgBVLiiS-j43QbeE6qgjIQo0pV3J8jtCAIPvJbO-Ex-GNkw_flgMiGHhKEpsHPW3WK-YZ-XsZJzVQ_pOmLte-Kql4z97WJvolqiXT0nMo2dlX2BGvNs6JNbupvcuGwL4YYpekYAaFNYMQrxi8bSN-R7FIqxP-gzZDAuQSWRRSUqVBLvmgRhphTM-FAx1sX833oXL9tR7ze3eDR_obSV0y6cKVIr4eIlKxFd82qiMrN6A6CTUFDeFjeAGERqeBPnJVXU36MHu7Ut7eOVav9OUARARWRkrZRkqzTfZ1iqEBq5Tsg'
# head = {'Authorization': 'Bearer {}'.format(my_token)}
# my_data={
# 'x' : f"{lng}",
# 'y' : f"{lat}",
# 'limit' : '1'
# }
# response = requests.post(f"{BASE_URL}/nearest_recycling/get", headers=head, data=my_data)
# infos = response.json()
# trashboxes = []
# for trashbox in infos["results"]:
# temp_dict = {}
# for obj in trashbox["Objects"]:
# coord_list = obj["geometry"]
# temp_dict["Lat"] = coord_list["coordinates"][1]
# temp_dict["Lng"] = coord_list["coordinates"][0]
# properties = obj["properties"]
# temp_dict["Name"] = properties["title"]
# temp_dict["Address"] = properties["address"]
# temp_dict["Categories"] = properties["content_text"].split(',')
# trashboxes.append(temp_dict)
# uniq_trashboxes = [ast.literal_eval(el1) for el1 in set([str(el2) for el2 in trashboxes])]
# return JSONResponse(uniq_trashboxes)
# @app.get("/{rest_of_path:path}")
# async def react_app(req: Request, rest_of_path: str):
# return templates.TemplateResponse('index.html', { 'request': req })
# >>>>>>> 3668e8c33f71b7a79a0c83d41a106d9b55e2df71
=======
>>>>>>> de8a1abcbfea61d8d4898c18e133b8b0feaf87e8

View File

@ -1,7 +1,7 @@
from sqlalchemy import Column, Integer, String from sqlalchemy import Column, Integer, String
from fastapi import Depends
from .db import Base from .db import Base
# from db import Base
class UserDatabase(Base):#класс пользователя class UserDatabase(Base):#класс пользователя
__tablename__ = "users" __tablename__ = "users"
@ -43,3 +43,20 @@ class Trashbox(Base):#класс мусорных баков
longtitude = Column(Integer) longtitude = Column(Integer)
category = Column(String)#категория продукта из объявления category = Column(String)#категория продукта из объявления
# 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)

View File

@ -1,5 +1,24 @@
from pydantic import BaseModel from pydantic import BaseModel
from typing import Annotated, Union
class Book(BaseModel): class Book(BaseModel):
id: int id: int
class Token(BaseModel):
access_token: str
token_type: str
class TokenData(BaseModel):
email: Union[str, None] = None
class User(BaseModel):
email: Union[str, None] = None
full_name: Union[str, None] = None
disabled: Union[bool, None] = None
class UserInDB(User):
hashed_password: str

View File

@ -5,10 +5,15 @@ from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt from jose import JWTError, jwt
from passlib.context import CryptContext from passlib.context import CryptContext
from pydantic import BaseModel
# to get a string like this run: from sqlalchemy.orm import Session
# openssl rand -hex 32 from sqlalchemy import select
from .db import SessionLocal, database
from .models import UserDatabase
from .schema import Token, TokenData, UserInDB, User
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7" SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256" ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30 ACCESS_TOKEN_EXPIRE_MINUTES = 30
@ -24,29 +29,6 @@ ACCESS_TOKEN_EXPIRE_MINUTES = 30
# } # }
# } # }
class Token(BaseModel):
access_token: str
token_type: str
class TokenData(BaseModel):
email: Union[str, None] = None
class User(BaseModel):
# email: str
email: Union[str, None] = None
# password: str
# password: Union[str, None] = None
full_name: Union[str, None] = None
disabled: Union[bool, None] = None
class UserInDB(User):
hashed_password: str
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
@ -60,17 +42,14 @@ def get_password_hash(password):
# проблема здесь # проблема здесь
def get_user(db, email: str): def get_user(db: SessionLocal, email: str):
user = None user_with_required_email = db.query(UserDatabase).filter(UserDatabase.email == email).one()
for person_with_correct_email in db.query(UserDatabase): if user_with_required_email:
if person_with_correct_email.email == email: return user_with_required_email
user = person_with_correct_email return None
return user #UserInDB(user_email)
def authenticate_user(db: SessionLocal, email: str, password: str):
def authenticate_user(db, email: str, password: str):
user = get_user(db, email) user = get_user(db, email)
if not user: if not user:
return False return False
@ -90,7 +69,7 @@ def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None
return encoded_jwt return encoded_jwt
async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]): async def get_current_user(db: SessionLocal, token: Annotated[str, Depends(oauth2_scheme)]):
credentials_exception = HTTPException( credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED, status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials", detail="Could not validate credentials",
@ -104,7 +83,7 @@ async def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]):
token_data = TokenData(email=email) token_data = TokenData(email=email)
except JWTError: except JWTError:
raise credentials_exception raise credentials_exception
user = get_user(fake_users_db, email=token_data.email) user = get_user(db, email=token_data.email)
if user is None: if user is None:
raise credentials_exception raise credentials_exception
return user return user