mirror of
https://github.com/devproje/balance-application.git
synced 2024-10-20 15:11:21 +00:00
feat: middle save
This commit is contained in:
parent
f6178a425c
commit
8d628e4826
8 changed files with 160 additions and 30 deletions
1
Makefile
Normal file
1
Makefile
Normal file
|
@ -0,0 +1 @@
|
||||||
|
|
6
app.py
6
app.py
|
@ -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)
|
||||||
|
|
19
generate.py
19
generate.py
|
@ -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
8
routes/auth.py
Normal 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 {}"}
|
|
@ -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
54
service/auth_service.py
Normal 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
|
|
@ -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
12
util/auth_lib.py
Normal 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
|
Loading…
Reference in a new issue