kimsaeromi commited on
Commit
c4d1e86
·
1 Parent(s): 6e755f8
app.py CHANGED
@@ -1,10 +1,12 @@
1
  from fastapi import FastAPI
2
- from routers import test_router
3
  import uvicorn
4
 
5
  app = FastAPI()
6
 
7
  app.include_router(test_router.router)
 
 
8
 
9
 
10
  @app.get("/")
@@ -18,4 +20,4 @@ if __name__ == "__main__":
18
  host="127.0.0.1",
19
  port=8000,
20
  reload=True
21
- )
 
1
  from fastapi import FastAPI
2
+ from routers import test_router, testdb_router, user_router
3
  import uvicorn
4
 
5
  app = FastAPI()
6
 
7
  app.include_router(test_router.router)
8
+ app.include_router(testdb_router.router)
9
+ app.include_router(user_router.router)
10
 
11
 
12
  @app.get("/")
 
20
  host="127.0.0.1",
21
  port=8000,
22
  reload=True
23
+ )
envinfo.text ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ POSTGRES_URL="postgres://postgres.hjgdlilnfccakdsmsypg:qBXsw226lYJabYgp@aws-1-ap-northeast-2.pooler.supabase.com:6543/postgres?sslmode=require"
2
+ POSTGRES_URL_ORIGINAL="postgres://postgres.hjgdlilnfccakdsmsypg:qBXsw226lYJabYgp@aws-1-ap-northeast-2.pooler.supabase.com:6543/postgres?sslmode=require&supa=base-pooler.x"
routers/test_router.py CHANGED
@@ -61,4 +61,4 @@ async def upload_file(file: UploadFile = File(...)):
61
  }
62
  return CommonResponse(success=True, data=data)
63
  except Exception as e:
64
- return CommonResponse(success=False, msg=str(e))
 
61
  }
62
  return CommonResponse(success=True, data=data)
63
  except Exception as e:
64
+ return CommonResponse(success=False, msg=str(e))
routers/testdb_router.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, Form, File, UploadFile
2
+ from utils.common import CommonResponse
3
+ from utils.db import get_connection
4
+
5
+ router = APIRouter(
6
+ prefix="/testdb",
7
+ tags=["testdb"]
8
+ )
9
+
10
+ @router.get("/")
11
+ def test_home():
12
+ try:
13
+ return CommonResponse(success=True)
14
+ except Exception as e:
15
+ return CommonResponse(success=False, msg=str(e))
16
+
17
+ @router.get("/now")
18
+ def select_now():
19
+ try:
20
+ with get_connection() as conn:
21
+ with conn.cursor() as cur:
22
+ cur.execute("select now()")
23
+ row = cur.fetchone()
24
+
25
+ data = {
26
+ "now": row[0].isoformat() if row else None
27
+ }
28
+ return CommonResponse(success=True, data=data)
29
+ except Exception as e:
30
+ return CommonResponse(success=False, msg=str(e))
31
+
32
+ @router.get("/select_test")
33
+ def select_now(id: int = 0):
34
+ try:
35
+ with get_connection() as conn:
36
+ with conn.cursor() as cur:
37
+ cur.execute("""
38
+ SELECT
39
+ *
40
+ FROM t_test
41
+ WHERE
42
+ CASE
43
+ WHEN %s != 0 THEN id = %s
44
+ ELSE TRUE
45
+ END
46
+ LIMIT 1000
47
+ """, [id, id])
48
+ row = cur.fetchall()
49
+
50
+ data = row
51
+ return CommonResponse(success=True, data=data)
52
+ except Exception as e:
53
+ return CommonResponse(success=False, msg=str(e))
54
+
55
+ @router.post("/upsert_test")
56
+ def upsert_test(id: int = Form(0), name: str = Form("")):
57
+ try:
58
+ with get_connection() as conn:
59
+ with conn.cursor() as cur:
60
+ if id <= 0:
61
+ cur.execute("""
62
+ INSERT INTO t_test (name)
63
+ VALUES (%s)
64
+ RETURNING id, name
65
+ """, [name])
66
+ else:
67
+ cur.execute("""
68
+ UPDATE t_test
69
+ SET name = %s
70
+ WHERE id = %s
71
+ RETURNING id, name
72
+ """, [name, id])
73
+
74
+ row = cur.fetchone()
75
+ if not row:
76
+ conn.rollback()
77
+ return CommonResponse(success=False, msg="data not found")
78
+
79
+ conn.commit()
80
+
81
+ data = {
82
+ "id": row[0],
83
+ "name": row[1]
84
+ }
85
+ return CommonResponse(success=True, data=data)
86
+ except Exception as e:
87
+ return CommonResponse(success=False, msg=str(e))
88
+
89
+ @router.post("/delete_test")
90
+ def delete_test(id: int = Form(0)):
91
+ try:
92
+ with get_connection() as conn:
93
+ with conn.cursor() as cur:
94
+ cur.execute("""
95
+ DELETE FROM t_test
96
+ WHERE id = %s
97
+ """, [id])
98
+
99
+ conn.commit()
100
+
101
+ data = {
102
+ "msg" : "delete success"
103
+ }
104
+ return CommonResponse(success=True, data=data)
105
+ except Exception as e:
106
+ return CommonResponse(success=False, msg=str(e))
routers/user_router.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, Form, File, UploadFile
2
+ from utils.common import CommonResponse
3
+ from utils.db import get_connection
4
+
5
+ router = APIRouter(
6
+ prefix="/user",
7
+ tags=["user"]
8
+ )
9
+
10
+ @router.post("/login_register")
11
+ def login_register(provider: str = Form(""), firebase_uid: str = Form(""),
12
+ email: str = Form(""),display_name: str = Form(""),
13
+ photo_url: str = Form("")):
14
+ try:
15
+ if firebase_uid == "":
16
+ return CommonResponse(success=False, msg="firebase_uid is required")
17
+ if email == "":
18
+ return CommonResponse(success=False, msg="email is required")
19
+
20
+ with get_connection() as conn:
21
+ with conn.cursor() as cur:
22
+ cur.execute("""
23
+ INSERT INTO t_user (
24
+ firebase_uid,
25
+ email,
26
+ display_name,
27
+ photo_url,
28
+ provider,
29
+ last_login_at
30
+ )
31
+ VALUES (
32
+ %s,
33
+ %s,
34
+ NULLIF(%s, ''),
35
+ NULLIF(%s, ''),
36
+ COALESCE(NULLIF(%s, ''), 'google'),
37
+ CURRENT_TIMESTAMP
38
+ )
39
+ ON CONFLICT (firebase_uid)
40
+ DO UPDATE SET
41
+ email = EXCLUDED.email,
42
+ display_name = EXCLUDED.display_name,
43
+ photo_url = EXCLUDED.photo_url,
44
+ provider = EXCLUDED.provider,
45
+ last_login_at = CURRENT_TIMESTAMP,
46
+ updated_at = CURRENT_TIMESTAMP
47
+ RETURNING
48
+ id,
49
+ firebase_uid,
50
+ email,
51
+ display_name,
52
+ photo_url,
53
+ provider,
54
+ role,
55
+ status,
56
+ last_login_at,
57
+ created_at,
58
+ updated_at
59
+ """, [firebase_uid, email, display_name, photo_url, provider])
60
+
61
+ row = cur.fetchone()
62
+ conn.commit()
63
+
64
+ data = {
65
+ "id": row[0],
66
+ "firebase_uid": row[1],
67
+ "email": row[2],
68
+ "display_name": row[3],
69
+ "photo_url": row[4],
70
+ "provider": row[5],
71
+ "role": row[6],
72
+ "status": row[7],
73
+ "last_login_at": row[8].isoformat() if row[8] else None,
74
+ "created_at": row[9].isoformat() if row[9] else None,
75
+ "updated_at": row[10].isoformat() if row[10] else None
76
+ }
77
+ return CommonResponse(success=True, data=data)
78
+ except Exception as e:
79
+ return CommonResponse(success=False, msg=str(e))
80
+
81
+ @router.post("/upload")
82
+ async def upload_file(file: UploadFile = File(...)):
83
+ try:
84
+ # business logic
85
+ contents = await file.read()
86
+ data = {
87
+ "filename": file.filename,
88
+ "content_type": file.content_type,
89
+ "size": len(contents)
90
+ }
91
+ return CommonResponse(success=True, data=data)
92
+ except Exception as e:
93
+ return CommonResponse(success=False, msg=str(e))
utils/common.py CHANGED
@@ -6,4 +6,5 @@ T = TypeVar("T")
6
  class CommonResponse(BaseModel, Generic[T]):
7
  success: bool=True
8
  data: Optional[T] = None
9
- msg: str = ""
 
 
6
  class CommonResponse(BaseModel, Generic[T]):
7
  success: bool=True
8
  data: Optional[T] = None
9
+ msg: str = ""
10
+
utils/db.py ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
3
+
4
+ import psycopg
5
+ from dotenv import load_dotenv
6
+
7
+ load_dotenv()
8
+
9
+ ALLOWED_POSTGRES_PARAMS = {
10
+ "application_name",
11
+ "connect_timeout",
12
+ "dbname",
13
+ "fallback_application_name",
14
+ "gssencmode",
15
+ "host",
16
+ "hostaddr",
17
+ "keepalives",
18
+ "keepalives_count",
19
+ "keepalives_idle",
20
+ "keepalives_interval",
21
+ "load_balance_hosts",
22
+ "options",
23
+ "passfile",
24
+ "password",
25
+ "port",
26
+ "replication",
27
+ "require_auth",
28
+ "requiressl",
29
+ "service",
30
+ "sslcert",
31
+ "sslcompression",
32
+ "sslcrl",
33
+ "sslcrldir",
34
+ "sslkey",
35
+ "sslmode",
36
+ "sslnegotiation",
37
+ "sslpassword",
38
+ "sslrootcert",
39
+ "sslsni",
40
+ "target_session_attrs",
41
+ "tcp_user_timeout",
42
+ "user",
43
+ }
44
+
45
+
46
+ def get_postgres_url():
47
+ postgres_url = os.getenv("POSTGRES_URL")
48
+ if not postgres_url:
49
+ raise ValueError("POSTGRES_URL is not set")
50
+
51
+ return clean_postgres_url(postgres_url)
52
+
53
+
54
+ def clean_postgres_url(postgres_url):
55
+ parts = urlsplit(postgres_url.strip().strip("\"'"))
56
+ query = urlencode(
57
+ [
58
+ (key, value)
59
+ for key, value in parse_qsl(parts.query, keep_blank_values=True)
60
+ if key in ALLOWED_POSTGRES_PARAMS
61
+ ]
62
+ )
63
+ return urlunsplit((parts.scheme, parts.netloc, parts.path, query, parts.fragment))
64
+
65
+
66
+ def get_connection():
67
+ return psycopg.connect(get_postgres_url())