feat: middle save

This commit is contained in:
Project_IO 2024-09-10 14:20:11 +09:00
parent f6178a425c
commit 8d628e4826
8 changed files with 160 additions and 30 deletions

1
Makefile Normal file
View file

@ -0,0 +1 @@

6
app.py
View file

@ -1,5 +1,6 @@
from routes.balance import router
from fastapi import FastAPI, Response
from routes.auth import router as auth
from routes.balance import router as balance
app = FastAPI()
@ -8,4 +9,5 @@ def index(resp: Response):
resp.headers.setdefault("Content-Type", "text")
return "Hello, World!"
app.include_router(router=router)
app.include_router(router=auth)
app.include_router(router=balance)

View file

@ -5,14 +5,31 @@ def __main__():
conn = psycopg2.connect(conn_param)
cur = conn.cursor()
cur.execute(
"""
create table account(
name varchar(25),
username varchar(25) primary key,
password varchar(50) not null,
salt varchar(50)
unique(username)
);
"""
)
cur.execute(
"""
create table balset(
id serial primary key,
uid varchar(25) not null,
name varchar(50),
date bigint,
price bigint,
memo varchar(300)
memo varchar(300),
constraint FK_Account_ID
foreign key (uid)
references account(username)
on delete CASCADE
);
"""
)

8
routes/auth.py Normal file
View file

@ -0,0 +1,8 @@
from fastapi import APIRouter
from service.auth_service import Credential
router = APIRouter()
@router.post("/auth/login")
def login(auth: Credential):
return {"ok": 1, "token": "Basic {}"}

View file

@ -5,14 +5,20 @@ from service.balance_service import Balance, BalanceService, UpdateForm
router = APIRouter()
@router.post("/balance", status_code=201)
def insert(balance: Balance):
def insert(balance: Balance, resp: Response):
started = datetime.now().microsecond / 1000
service = BalanceService()
name = service.create(balance=balance)
ok = service.create(balance=balance)
if not ok == 1:
resp.status_code = 500
return {
"ok": 0,
"errno": "error occurred to running transaction"
}
return {
"ok": 1,
"name": name,
"name": balance.name,
"respond_time": "{}ms".format(round((datetime.now().microsecond / 1000) - started))
}
@ -63,7 +69,7 @@ def update(action, id, balance: UpdateForm, resp: Response):
"errno": "memo value size is too long: (maximum size: 300 bytes, your size: {} bytes)".format(len(balance.memo))
}
service.update(
ok = service.update(
int(id),
action, {
"name": balance.name,
@ -73,6 +79,13 @@ def update(action, id, balance: UpdateForm, resp: Response):
}
)
if not ok == 1:
resp.status_code = 500
return {
"ok": 0,
"errno": "error occurred to running transaction"
}
return {
"ok": 1,
"id": int(id),
@ -80,10 +93,16 @@ def update(action, id, balance: UpdateForm, resp: Response):
}
@router.delete("/balance/{id}")
def delete(id):
def delete(id, resp: Response):
started = datetime.now().microsecond / 1000
service = BalanceService()
service.delete(int(id))
ok = service.delete(int(id))
if not ok == 1:
resp.status_code = 500
return {
"ok": 0,
"errno": "error occurred to running transaction"
}
return {
"ok": 1,

54
service/auth_service.py Normal file
View file

@ -0,0 +1,54 @@
import base64, psycopg2
from fastapi import Request
from pydantic import BaseModel
from util.config import conn_param
class AuthData:
name: str
username: str
password: str
salt: str
class Register:
name: str
username: str
password: str
class Credential(BaseModel):
username: str
password: str
class AuthService:
def __init__(self):
self._conn = psycopg2.connect(conn_param)
def read(self, username: str):
cur = self._conn.cursor()
cur.execute("select * from account where username = %s;", (username))
data = cur.fetchone()
if data == None:
return None
cur.close()
self._conn.close()
return AuthData(
name = data[0],
username = data[1],
password = data[2],
salt = data[3]
)
def check_auth(self, req: Request) -> bool:
raw = req.headers.get("Authorization")
raw_token = raw.removeprefix("Basic ").encode("ascii")
token = base64.b64decode(raw_token)
data = token.decode("utf-8").split(":")
acc = self.read(data[0])
if acc.username == data[0] and acc.password == data[1]:
return True
return False

View file

@ -18,19 +18,24 @@ class BalanceService:
def __init__(self):
self._conn = psycopg2.connect(conn_param)
def create(self, balance: Balance) -> str:
def create(self, balance: Balance):
ok = True
cur = self._conn.cursor()
try:
cur.execute(
"insert into balset(name, date, price, memo) values (%s, %s, %s, %s);",
(balance.name, balance.date, balance.price, balance.memo)
)
self._conn.commit()
except:
self._conn.rollback()
ok = False
finally:
cur.close()
self._conn.close()
return balance.name
return ok
def read(self, id: int):
cur = self._conn.cursor()
@ -53,19 +58,31 @@ class BalanceService:
}
def update(self, id: int, act: str, balance: UpdateForm):
ok = True
cur = self._conn.cursor()
try:
cur.execute(f"update balset set {act} = %s where id = %s;", (balance[act], id))
self._conn.commit()
except:
self._conn.rollback()
ok = False
finally:
cur.close()
self._conn.close()
return ok
def delete(self, id: int):
ok = True
cur = self._conn.cursor()
try:
cur.execute("delete from balset where id = %s;", (id))
self._conn.commit()
except:
self._conn.rollback()
ok = False
finally:
cur.close()
self._conn.close()
return ok

12
util/auth_lib.py Normal file
View file

@ -0,0 +1,12 @@
import base64
from hashlib import sha256
def hash(password: str, salt: str):
return sha256("{}:{}".format(password, salt))
def gen_token(username: str, hashed_password: str):
raw = ("{}:{}".format(username, hashed_password)).encode("utf-8")
raw_token = base64.b64encode(raw)
token = raw_token.decode("ascii")
return token