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 fastapi import FastAPI, Response
from routes.auth import router as auth
from routes.balance import router as balance
app = FastAPI() app = FastAPI()
@ -8,4 +9,5 @@ def index(resp: Response):
resp.headers.setdefault("Content-Type", "text") resp.headers.setdefault("Content-Type", "text")
return "Hello, World!" 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) conn = psycopg2.connect(conn_param)
cur = conn.cursor() 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( cur.execute(
""" """
create table balset( create table balset(
id serial primary key, id serial primary key,
uid varchar(25) not null,
name varchar(50), name varchar(50),
date bigint, date bigint,
price 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 = APIRouter()
@router.post("/balance", status_code=201) @router.post("/balance", status_code=201)
def insert(balance: Balance): def insert(balance: Balance, resp: Response):
started = datetime.now().microsecond / 1000 started = datetime.now().microsecond / 1000
service = BalanceService() 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 { return {
"ok": 1, "ok": 1,
"name": name, "name": balance.name,
"respond_time": "{}ms".format(round((datetime.now().microsecond / 1000) - started)) "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)) "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), int(id),
action, { action, {
"name": balance.name, "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 { return {
"ok": 1, "ok": 1,
"id": int(id), "id": int(id),
@ -80,10 +93,16 @@ def update(action, id, balance: UpdateForm, resp: Response):
} }
@router.delete("/balance/{id}") @router.delete("/balance/{id}")
def delete(id): def delete(id, resp: Response):
started = datetime.now().microsecond / 1000 started = datetime.now().microsecond / 1000
service = BalanceService() 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 { return {
"ok": 1, "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): def __init__(self):
self._conn = psycopg2.connect(conn_param) self._conn = psycopg2.connect(conn_param)
def create(self, balance: Balance) -> str: def create(self, balance: Balance):
ok = True
cur = self._conn.cursor() cur = self._conn.cursor()
cur.execute( try:
"insert into balset(name, date, price, memo) values (%s, %s, %s, %s);", cur.execute(
(balance.name, balance.date, balance.price, balance.memo) "insert into balset(name, date, price, memo) values (%s, %s, %s, %s);",
) (balance.name, balance.date, balance.price, balance.memo)
)
self._conn.commit() self._conn.commit()
except:
self._conn.rollback()
ok = False
finally:
cur.close()
self._conn.close()
cur.close() return ok
self._conn.close()
return balance.name
def read(self, id: int): def read(self, id: int):
cur = self._conn.cursor() cur = self._conn.cursor()
@ -53,19 +58,31 @@ class BalanceService:
} }
def update(self, id: int, act: str, balance: UpdateForm): def update(self, id: int, act: str, balance: UpdateForm):
ok = True
cur = self._conn.cursor() cur = self._conn.cursor()
cur.execute(f"update balset set {act} = %s where id = %s;", (balance[act], id)) 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()
self._conn.commit() return ok
cur.close()
self._conn.close()
def delete(self, id: int): def delete(self, id: int):
ok = True
cur = self._conn.cursor() cur = self._conn.cursor()
cur.execute("delete from balset where id = %s;", (id)) 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()
self._conn.commit() return ok
cur.close()
self._conn.close()

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