Commit cc9195c2 authored by Ai-Sasit's avatar Ai-Sasit

initial commit

parents
Pipeline #1642 failed with stages
.vercel
__pycache__
venv/
.env
\ No newline at end of file
#
FROM python:3.9
#
WORKDIR /code
#
COPY ./requirements.txt /code/requirements.txt
#
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
#
COPY ./server /code/server
#
CMD ["uvicorn", "server.core:app", "--host", "0.0.0.0", "--port", "80"]
import uvicorn
if __name__ == "__main__":
uvicorn.run("server.core:app", host="0.0.0.0", port=8000, reload=True)
\ No newline at end of file
import re
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from server.routes.scb_service import scb
from server.routes.user import user
from server.routes.shop import shop
from server.routes.category import cat
from server.routes.table import table
from server.routes.menu import menu
version = '1.2.0'
app = FastAPI(docs_url="/api/docs", openapi_url="/api", title="Database REST API For Easy Bistro", version=version)
origins = [
"http://localhost:8080",
"https://easybistro-office.web.app",
"https://easybistro-owner-manager.web.app",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
def read_root():
return {"Project":"Easy Bistro", "Framework": "Fast API", "Interpreter":"Python", 'API Version': version}
app.include_router(scb, prefix="/v1", tags=["SCB API"])
app.include_router(user, prefix="/api", tags=["Office User"])
app.include_router(shop, prefix="/api", tags=["Shop"])
app.include_router(cat, prefix="/api", tags=["Category"])
app.include_router(table, prefix="/api", tags=["Table"])
app.include_router(menu, prefix="/api", tags=["Menu"])
def User_helper(user) -> dict:
return {
"id": str(user["_id"]),
"username": str(user["username"]),
"email": str(user["email"]),
"password": str(user["password"])
}
def Shop_helper(shop) -> dict:
return {
"id": str(shop["_id"]),
"name": str(shop["name"]),
"email": str(shop["email"]),
"tel": str(shop["tel"]),
"owner": str(shop["owner"]),
"secret": str(shop["secret"])
}
def Category_helper(category) -> dict:
return {
'id': str(category["_id"]),
'shop_id': str(category["shop_id"]),
'name': str(category["name"]),
}
def Table_helper(table) -> dict:
return {
'id': str(table['_id']),
'shop_id': str(table["shop_id"]),
'session_key': str(table['session_key']),
'name': str(table['name']),
'sit_number': str(table["sit_number"]),
'status': bool(table['status'])
}
def Menu_helper(menu) -> dict:
return {
'id': str(menu['_id']),
'shop_id': str(menu['shop_id']),
'status': bool(menu['status']),
'name': str(menu['name']),
'category': str(menu['category']),
'price': str(menu['price']),
'images': list(menu['images'])
}
\ No newline at end of file
from typing import Optional
from pydantic import BaseModel
class OfficeUser(BaseModel):
username:str
email:str
password:str
class TokenUser(BaseModel):
username: Optional[str] = None
email: Optional[str] = None
class Shop(BaseModel):
name: str
tel: str
email: str
owner: str
secret: str
class TokenShop(BaseModel):
id: Optional[str] = None
name: Optional[str] = None
owner: Optional[str] = None
class Category(BaseModel):
shop_id: str
name:str
class Table(BaseModel):
shop_id: str
session_key:str
name:str
sit_number:str
status:bool
class Menu(BaseModel):
shop_id: str
status: bool
name:str
category: str
price:str
images: list
\ No newline at end of file
from fastapi import APIRouter
from bson.objectid import ObjectId
from server.mock.schemas import Category
from server.mock.model import Category_helper
from server.service.database import get_connection
cat = APIRouter()
collection = get_connection('category')
@cat.get('/category/{sid}')
async def get_category(sid: str):
return [Category_helper(i) for i in collection.find({'shop_id': sid})]
@cat.get('/category/{sid}/{id}')
async def get_category_by_id(sid: str, id: str):
category = collection.find_one({"_id": ObjectId(id), "shop_id": sid})
return Category_helper(category)
@cat.post('/category')
async def create_category(category: Category):
payload = {
'shop_id': category.shop_id,
'name': category.name
}
collection.insert_one(payload)
return [Category_helper(i) for i in collection.find({'shop_id': category.shop_id})]
@cat.patch('/category/{sid}/{id}')
async def update_category(sid: str, id: str, category: Category):
payload = {
'name': category.name,
}
collection.update_one({"_id": ObjectId(id)}, {"$set": payload})
return [Category_helper(i) for i in collection.find({"shop_id": sid})]
@cat.delete('/category/{sid}/{id}')
async def delete_category(sid:str, id: str):
collection.delete_one({"_id": ObjectId(id)})
return [Category_helper(i) for i in collection.find({"shop_id": sid})]
from fastapi import APIRouter
from bson.objectid import ObjectId
from server.mock.schemas import Menu
from server.mock.model import Menu_helper
from server.service.database import get_connection
menu = APIRouter()
collection = get_connection('Menu')
@menu.get('/menu/{sid}')
async def get_menu(sid: str):
return [Menu_helper(i) for i in collection.find({'shop_id': sid})]
@menu.get('/menu/{sid}/{id}')
async def get_menu_by_id(sid: str, id: str):
menu = collection.find_one({"_id": ObjectId(id), 'shop_id': sid})
return Menu_helper(menu)
@menu.post('/menu/')
async def create_menu(menu: Menu):
payload = {
'shop_id' : menu.shop_id,
'status': menu.status,
'name': menu.name,
'category': menu.category,
'price': menu.price,
'images': menu.images,
}
collection.insert_one(payload)
return [Menu_helper(i) for i in collection.find({'shop_id': menu.shop_id})]
@menu.patch('/menu/{sid}/{id}')
async def update_menu(sid: str, id: str, menu: Menu):
payload = {
'name': menu.name,
'price': menu.price,
'category': menu.category,
}
collection.update_one({"_id": ObjectId(id)}, {"$set": payload})
return [Menu_helper(i) for i in collection.find({'shop_id': sid})]
@menu.patch('/menu_status/{sid}/{id}')
async def update_menu_status(sid: str, id: str, menu: Menu):
payload = {
'status': menu.status,
}
collection.update_one({"_id": ObjectId(id)}, {"$set": payload})
return [Menu_helper(i) for i in collection.find({'shop_id': sid})]
@menu.delete('/menu/{sid}/{id}')
async def delete_menu(sid: str, id: str):
collection.delete_one({"_id": ObjectId(id)})
return [Menu_helper(i) for i in collection.find({'shop_id': sid})]
\ No newline at end of file
from fastapi import APIRouter, Request
scb = APIRouter()
temp = []
@scb.post("/scb/confirm_payment")
async def confirm_payment(req: Request):
temp.append(req.json())
return await req.json()
@scb.get("/scb/await_callback")
def await_callback():
if temp:
temp.pop(0)
return {"SCB": True}
else:
return {"SCB": False}
\ No newline at end of file
from fastapi.security import OAuth2PasswordRequestForm
from fastapi import APIRouter, Depends
from bson.objectid import ObjectId
from server.service.jwttoken import create_access_token
from server.service.oauth import get_current_shop
from server.service.database import get_connection
from server.mock.model import Shop_helper
from server.mock.schemas import Shop
collection = get_connection("shop")
shop = APIRouter()
@shop.get("/shop")
async def get_shop():
return [Shop_helper(i) for i in collection.find()]
@shop.get("/shop/{id}")
async def get_shop_by_id(id: str):
shop = collection.find_one({"_id": ObjectId(id)})
return Shop_helper(shop)
@shop.post("/shop")
async def create_shop(shop: Shop):
payload = {
"name": shop.name,
"email": shop.email,
"tel": shop.tel,
"owner": shop.owner,
"secret": shop.secret
}
collection.insert_one(payload)
return [Shop_helper(i) for i in collection.find()]
@shop.patch("/shop/{id}")
async def update_shop(id: str, shop: Shop):
payload = {
"name": shop.name,
"email": shop.email,
"tel": shop.tel,
"owner": shop.owner
}
collection.update_one({"_id": ObjectId(id)}, {"$set": payload})
return [Shop_helper(i) for i in collection.find()]
@shop.delete("/shop/{id}")
async def delete_shop(id: str):
collection.delete_one({"_id": ObjectId(id)})
return [Shop_helper(i) for i in collection.find()]
@shop.post("/shop_login")
async def login_shop(req: OAuth2PasswordRequestForm = Depends()):
secret = req.password
shop_account = collection.find_one({"secret": secret})
if shop_account is None:
return {"error": "Account not found"}
format_shop = Shop_helper(shop_account)
access_token = create_access_token({"id": format_shop["id"], "owner": format_shop["owner"], "name": format_shop["name"]})
return {"access_token":access_token, "token_type": "Bearer"}
@shop.get("/shop_verify_account")
async def verify_shop_account(current_shop: Shop = Depends(get_current_shop)):
return current_shop
\ No newline at end of file
import re
from fastapi import APIRouter
from bson.objectid import ObjectId
from server.mock.schemas import Table
from server.mock.model import Table_helper
from server.service.database import get_connection
table = APIRouter()
collection = get_connection('table')
@table.get('/table/{sid}')
async def get_table(sid:str):
return [Table_helper(i) for i in collection.find({'shop_id': sid})]
@table.get('/table/{sid}/{id}')
async def get_table_by_id(sid: str, id: str):
table = collection.find_one({'shop_id': sid, '_id': ObjectId(id)})
return Table_helper(table)
@table.post('/table')
async def create_table(table: Table):
payload = {
'shop_id' : table.shop_id,
'session_key' : table.session_key,
'name' : table.name,
'sit_number' : table.sit_number,
'status' : table.status
}
collection.insert_one(payload)
return [Table_helper(i) for i in collection.find({'shop_id': table.shop_id})]
@table.patch('/table_data/{sid}/{id}')
async def update_table_data(sid: str, id: str, table: Table):
payload = {
'name': table.name,
'sit_number': table.sit_number
}
collection.update_one({"_id": ObjectId(id)}, {"$set": payload})
return [Table_helper(i) for i in collection.find({'shop_id': sid})]
@table.patch('/table_status/{sid}/{id}')
async def update_table_status(sid: str, id: str, table: Table):
payload = {
'session_key': table.session_key,
'status': table.status,
}
collection.update_one({"_id": ObjectId(id)}, {"$set": payload})
return [Table_helper(i) for i in collection.find({'shop_id': sid})]
@table.delete("/table/{sid}/{id}")
async def delete_table(sid: str, id: str):
collection.delete_one({"_id": ObjectId(id)})
return [Table_helper(i) for i in collection.find({'shop_id': sid})]
# @table.get("/verify_table/{key}")
# async def verify_table(key: str):
# table = collection.find_one({"session_key": key})
# if table is None:
# return {"status": "Table session have no longer"}
# else:
# return {"status": True}
\ No newline at end of file
from fastapi import APIRouter, Depends
from fastapi.security import OAuth2PasswordRequestForm
from bson.objectid import ObjectId
from server.service.jwttoken import create_access_token
from server.service.oauth import get_current_user
from server.service.hashing import Hash
from server.service.database import get_connection
from server.mock.model import User_helper
from server.mock.schemas import OfficeUser
collection = get_connection("Office_User")
user = APIRouter()
@user.get("/users")
async def get_users():
users = []
for i in collection.find():
users.append(User_helper(i))
return users
@user.get("/users/{id}")
async def get_user_by_id(id:str):
user = collection.find_one({"_id": ObjectId(id)})
return User_helper(user)
@user.post("/user/")
async def create_user(user: OfficeUser):
payload = {
"username": user.username,
"email": user.email,
"password": Hash.bcrypt(user.password)
}
user = collection.insert_one(payload)
new_user = collection.find_one({"_id":user.inserted_id})
return User_helper(new_user)
@user.patch("/user/{id}")
async def update_user(id:str ,user: OfficeUser):
payload = {
"username": user.username,
"email": user.email,
}
collection.update_one({"_id",ObjectId(id)},{"$set": payload })
update_user = collection.find_one({"_id":ObjectId(id)})
return User_helper(update_user)
@user.delete("/user/{id}")
async def delete_user(id: str):
collection.delete_one({"_id":ObjectId(id)})
users = []
for i in collection.find():
users.append(User_helper(i))
return users
@user.post("/login")
async def login(req:OAuth2PasswordRequestForm = Depends()):
user = collection.find_one({"username": req.username})
if user is None:
return {"error": "User not found"}
format_user = User_helper(user)
if not Hash.verify(format_user["password"],req.password):
return {"error": "Invalid password"}
access_token = create_access_token({"username": format_user["username"],"email": format_user["email"]})
return {"access_token":access_token, "token_type": "Bearer"}
@user.get("/verify_user")
async def verify_token_user(current_user: OfficeUser = Depends(get_current_user)):
return current_user
\ No newline at end of file
import pymongo
def get_connection(collection:str):
client = pymongo.MongoClient('mongodb+srv://SasitAi:Tackle123@easybistro.7qdtgg2.mongodb.net/Easybistro')
return client['easybistro'][collection]
from passlib.context import CryptContext
pwd_cxt = CryptContext(schemes =["bcrypt"],deprecated="auto")
class Hash():
def bcrypt(password:str):
return pwd_cxt.hash(password)
def verify(hashed,plaintext):
return pwd_cxt.verify(plaintext,hashed)
from datetime import datetime, timedelta
from server.mock.schemas import TokenUser, TokenShop
from jose import JWTError, jwt
# from main import TokenData
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 60
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
def verify_token(token:str,credentials_exception):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("username")
email: str = payload.get("email")
if username is None:
raise credentials_exception
token_data = TokenUser(username=username, email=email)
return token_data
except JWTError:
return {"error": "Invalid token"}
def verify_shop_token(token:str,credentials_exception):
try:
payload = jwt.decode(token,SECRET_KEY, algorithms=[ALGORITHM])
id: str = payload.get("id")
name: str = payload.get("name")
owner: str = payload.get("owner")
if id is None:
raise credentials_exception
token_data = TokenShop(id=id, name=name, owner=owner)
return token_data
except JWTError:
return {"error":"Invalid token"}
\ No newline at end of file
from fastapi import Depends,HTTPException,status
from server.service.jwttoken import verify_shop_token, verify_token
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login")
oauth2_shop_scheme = OAuth2PasswordBearer(tokenUrl="shop_login")
def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
return verify_token(token,credentials_exception)
def get_current_shop(token: str = Depends(oauth2_shop_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
return verify_shop_token(token,credentials_exception)
\ No newline at end of file
{
"builds": [
{"src": "/server/core.py", "use": "@vercel/python"}
],
"routes": [
{"src": "/(.*)", "dest": "server/core.py"}
]
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment