edit: faiss 전용 rest 서버 추가
This commit is contained in:
93
main_rest/app/routes/auth.py
Normal file
93
main_rest/app/routes/auth.py
Normal file
@@ -0,0 +1,93 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@File: auth.py
|
||||
@Date: 2020-09-14
|
||||
@author: A2TEC
|
||||
@section MODIFYINFO 수정정보
|
||||
- 수정자/수정일 : 수정내역
|
||||
- 2022-01-14/hsj100@a2tec.co.kr : refactoring
|
||||
@brief: authentication api
|
||||
"""
|
||||
|
||||
from itertools import groupby
|
||||
from operator import attrgetter
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
import bcrypt
|
||||
import jwt
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from main_rest.app.common import consts
|
||||
from main_rest.app import models as M
|
||||
from main_rest.app.database.conn import db
|
||||
from main_rest.app.common.config import conf
|
||||
from main_rest.app.database.schema import Users, UserLog
|
||||
from main_rest.app.utils.extra import query_to_groupby, AESCryptoCBC
|
||||
from main_rest.app.utils.date_utils import D
|
||||
|
||||
router = APIRouter(prefix='/auth')
|
||||
|
||||
|
||||
@router.get('/find-account/{account}', response_model=M.ResponseBase, summary='계정유무 검사')
|
||||
async def find_account(account: str):
|
||||
"""
|
||||
## 계정유무 검사
|
||||
|
||||
주어진 계정이 존재하면 true, 없으면 false 처리
|
||||
|
||||
**결과**
|
||||
- ResponseBase
|
||||
"""
|
||||
try:
|
||||
search_info = Users.get(account=account)
|
||||
if not search_info:
|
||||
raise Exception(f'not found data: {account}')
|
||||
return M.ResponseBase()
|
||||
except Exception as e:
|
||||
return M.ResponseBase.set_error(str(e))
|
||||
|
||||
|
||||
@router.post('/logout/{account}', status_code=200, response_model=M.TokenRes, summary='사용자 접속종료')
|
||||
async def logout(account: str):
|
||||
"""
|
||||
## 사용자 접속종료
|
||||
|
||||
현재 버전에서는 로그인/로그아웃의 상태를 유지하지 않고 상태값만을 서버에서 사용하기 때문에,\n
|
||||
***로그상태는 실제상황과 다를 수 있다.***
|
||||
|
||||
정상처리시 Authorization(null) 반환
|
||||
|
||||
**결과**
|
||||
- TokenRes
|
||||
"""
|
||||
user_info = None
|
||||
|
||||
try:
|
||||
# TODO(hsj100): LOGIN_STATUS
|
||||
user_info = Users.filter(account=account)
|
||||
if not user_info:
|
||||
raise Exception('not found user')
|
||||
|
||||
user_info.update(auto_commit=True, login='logout')
|
||||
return M.TokenRes()
|
||||
except Exception as e:
|
||||
if user_info:
|
||||
user_info.close()
|
||||
return M.ResponseBase.set_error(e)
|
||||
|
||||
|
||||
async def is_account_exist(account: str):
|
||||
get_account = Users.get(account=account)
|
||||
return True if get_account else False
|
||||
|
||||
|
||||
def create_access_token(*, data: dict = None, expires_delta: int = None):
|
||||
|
||||
if conf().GLOBAL_TOKEN:
|
||||
return conf().GLOBAL_TOKEN
|
||||
|
||||
to_encode = data.copy()
|
||||
if expires_delta:
|
||||
to_encode.update({'exp': datetime.utcnow() + timedelta(hours=expires_delta)})
|
||||
encoded_jwt = jwt.encode(to_encode, consts.JWT_SECRET, algorithm=consts.JWT_ALGORITHM)
|
||||
return encoded_jwt
|
||||
137
main_rest/app/routes/dev.py
Normal file
137
main_rest/app/routes/dev.py
Normal file
@@ -0,0 +1,137 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@File: dev.py
|
||||
@Date: 2020-09-14
|
||||
@author: A2TEC
|
||||
@section MODIFYINFO 수정정보
|
||||
- 수정자/수정일 : 수정내역
|
||||
- 2022-01-14/hsj100@a2tec.co.kr : refactoring
|
||||
@brief: Developments Test
|
||||
"""
|
||||
import struct
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
import bcrypt
|
||||
from starlette.requests import Request
|
||||
|
||||
from main_rest.app.common import consts
|
||||
from main_rest.app import models as M
|
||||
from main_rest.app.database.conn import db, Base
|
||||
from main_rest.app.database.schema import Users, UserLog
|
||||
|
||||
from main_rest.app.utils.extra import FernetCrypto, AESCryptoCBC, AESCipher
|
||||
from custom_logger.main_log import main_logger as LOG
|
||||
|
||||
|
||||
# mail test
|
||||
import smtplib
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
|
||||
|
||||
def send_mail():
|
||||
"""
|
||||
구글 계정사용시 : 보안 수준이 낮은 앱에서의 접근 활성화
|
||||
|
||||
:return:
|
||||
"""
|
||||
sender = 'jolimola@gmail.com'
|
||||
sender_pw = '!ghkdtmdwns1'
|
||||
# recipient = 'hsj100@a2tec.co.kr'
|
||||
recipient = 'jwkim@daooldns.co.kr'
|
||||
list_cc = ['cc1@gmail.com', 'cc2@naver.com']
|
||||
str_cc = ','.join(list_cc)
|
||||
|
||||
title = 'Test mail'
|
||||
contents = '''
|
||||
This is test mail
|
||||
using smtplib.
|
||||
'''
|
||||
|
||||
smtp_server = smtplib.SMTP( # 1
|
||||
host='smtp.gmail.com',
|
||||
port=587
|
||||
)
|
||||
|
||||
smtp_server.ehlo() # 2
|
||||
smtp_server.starttls() # 2
|
||||
smtp_server.ehlo() # 2
|
||||
smtp_server.login(sender, sender_pw) # 3
|
||||
|
||||
msg = MIMEMultipart() # 4
|
||||
msg['From'] = sender # 5
|
||||
msg['To'] = recipient # 5
|
||||
# msg['Cc'] = str_cc # 5
|
||||
msg['Subject'] = contents # 5
|
||||
msg.attach(MIMEText(contents, 'plain')) # 6
|
||||
|
||||
smtp_server.send_message(msg) # 7
|
||||
smtp_server.quit() # 8
|
||||
|
||||
|
||||
router = APIRouter(prefix='/dev')
|
||||
|
||||
|
||||
@router.get('/test', summary='테스트', response_model=M.SWInfo)
|
||||
async def test(request: Request):
|
||||
"""
|
||||
## ELB 상태 체크용 API
|
||||
|
||||
**결과**
|
||||
- SWInfo
|
||||
"""
|
||||
|
||||
a = M.SWInfo()
|
||||
|
||||
a.name = '!ekdnfeldpsdptm1'
|
||||
# a.name = 'testtesttest123'
|
||||
simpleEnDecrypt = FernetCrypto()
|
||||
a.data1 = simpleEnDecrypt.encrypt(a.name)
|
||||
a.data2 = bcrypt.hashpw(a.name.encode('utf-8'), bcrypt.gensalt())
|
||||
|
||||
t = bytes(a.name.encode('utf-8'))
|
||||
|
||||
enc = AESCryptoCBC().encrypt(t)
|
||||
dec = AESCryptoCBC().decrypt(enc)
|
||||
|
||||
t = enc.decode('utf-8')
|
||||
|
||||
# enc = AESCipher('daooldns12345678').encrypt(a.name).decode('utf-8')
|
||||
# enc = 'E563ZFt+yJL8YY5yYlYyk602MSscPP2SCCD8UtXXpMI='
|
||||
# dec = AESCipher('daooldns12345678').decrypt(enc).decode('utf-8')
|
||||
|
||||
a.data3 = f'enc: {enc}, {t}'
|
||||
a.data4 = f'dec: {dec}'
|
||||
|
||||
a.name = '!ekdnfeldpsdptm1'
|
||||
|
||||
|
||||
# simpleEnDecrypt = SimpleEnDecrypt()
|
||||
a.data5 = simpleEnDecrypt.encrypt(a.name)
|
||||
a.data6 = bcrypt.hashpw(a.name.encode('utf-8'), bcrypt.gensalt())
|
||||
|
||||
key = consts.ADMIN_INIT_ACCOUNT_INFO['aes_cbc_key']
|
||||
|
||||
t = bytes(a.name.encode('utf-8'))
|
||||
|
||||
enc = AESCryptoCBC(key).encrypt(t)
|
||||
dec = AESCryptoCBC(key).decrypt(enc)
|
||||
|
||||
t = enc.decode('utf-8')
|
||||
|
||||
# enc = AESCipher('daooldns12345678').encrypt(a.name).decode('utf-8')
|
||||
# enc = 'E563ZFt+yJL8YY5yYlYyk602MSscPP2SCCD8UtXXpMI='
|
||||
# dec = AESCipher('daooldns12345678').decrypt(enc).decode('utf-8')
|
||||
|
||||
print(f'key: {key}')
|
||||
a.data7 = f'enc: {enc}, {t}'
|
||||
a.data8 = f'dec: {dec}'
|
||||
|
||||
|
||||
eee = "gAAAAABioV5NucuS9nQugZJnz-KjVG_FGnaowB9KAfhOoWjjiQ4jGLuYJh4Qe94mT_lCm6m3HhuOJqUeOgjppwREDpIQYzrUXA=="
|
||||
a.data8 = simpleEnDecrypt.decrypt(eee)
|
||||
|
||||
return a
|
||||
|
||||
|
||||
32
main_rest/app/routes/index.py
Normal file
32
main_rest/app/routes/index.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@File: index.py
|
||||
@Date: 2020-09-14
|
||||
@author: A2TEC
|
||||
@section MODIFYINFO 수정정보
|
||||
- 수정자/수정일 : 수정내역
|
||||
- 2022-01-14/hsj100@a2tec.co.kr : refactoring
|
||||
@brief: basic & test api
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter
|
||||
|
||||
from main_rest.app.utils.date_utils import D
|
||||
from main_rest.app.models import SWInfo
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get('/', summary='서비스 정보', response_model=SWInfo)
|
||||
async def index():
|
||||
"""
|
||||
## 서비스 정보
|
||||
소프트웨어 이름, 버전정보, 현재시간
|
||||
|
||||
**결과**
|
||||
- SWInfo
|
||||
"""
|
||||
sw_info = SWInfo()
|
||||
sw_info.date = D.date_str()
|
||||
return sw_info
|
||||
183
main_rest/app/routes/services.py
Normal file
183
main_rest/app/routes/services.py
Normal file
@@ -0,0 +1,183 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@File: services.py
|
||||
@Date: 2020-09-14
|
||||
@author: A2TEC
|
||||
@section MODIFYINFO 수정정보
|
||||
- 수정자/수정일 : 수정내역
|
||||
- 2022-01-14/hsj100@a2tec.co.kr : refactoring
|
||||
@brief: services api
|
||||
"""
|
||||
|
||||
import requests, json, traceback
|
||||
from fastapi import APIRouter, Depends, Body
|
||||
from starlette.requests import Request
|
||||
from typing import Annotated, List
|
||||
|
||||
from main_rest.app.common import consts
|
||||
from main_rest.app import models as M
|
||||
from main_rest.app.utils.date_utils import D
|
||||
from custom_logger.main_log import main_logger as LOG
|
||||
|
||||
from custom_apps.bingimagecreator.utils import DallEArgument,dalle3_generate_image
|
||||
from custom_apps.bingart.bingart import BingArtGenerator
|
||||
from custom_apps.imagen.custom_imagen import imagen_generate_image, imagen_generate_image_path
|
||||
from main_rest.app.utils.parsing_utils import download_range
|
||||
from custom_apps.utils import cookie_manager
|
||||
|
||||
router = APIRouter(prefix="/services")
|
||||
|
||||
@router.post("/bing/cookie/set", summary="bing 관련 쿠키 set", response_model=M.BingCookieSetRes)
|
||||
async def bing_cookie_set(request: Request, request_body_info: M.BingCookieSetReq):
|
||||
"""
|
||||
## Bing cookie set
|
||||
> 쿠키정보 set
|
||||
|
||||
## 정보
|
||||
> cookie 값이 빈 값일경우 쿠키정보를 set 하지 않고 현재 쿠키값 return 함
|
||||
> cookie 값이 정상 쿠키 인지는 확인안함
|
||||
|
||||
"""
|
||||
response = M.BingCookieSetRes()
|
||||
try:
|
||||
if len(request_body_info.cookie) == 0:
|
||||
pass
|
||||
else:
|
||||
cookie_manager.set_cookie(request_body_info.cookie)
|
||||
|
||||
return response.set_message(current_cookie=cookie_manager.get_cookie())
|
||||
|
||||
except Exception as e:
|
||||
LOG.error(traceback.format_exc())
|
||||
return response.set_error(e,current_cookie=cookie_manager.get_cookie())
|
||||
|
||||
|
||||
@router.post("/imageGenerate/bingimg", summary="이미지 생성(AI) - bing image generator (DALL-E 3)", response_model=M.ImageGenerateRes)
|
||||
async def bing_img_generate(request: Request, request_body_info: M.ImageGenerateReq):
|
||||
"""
|
||||
## 이미지 생성(AI) - bing image generator (DALL-E 3)
|
||||
> bing image generator를 이용하여 이미지 생성
|
||||
|
||||
### Requriements
|
||||
|
||||
|
||||
## 정보
|
||||
> 오류 발생시 오류 발생한 파일은 에러 메세지에만 남기고 저장은 안함
|
||||
> *동작 안함.
|
||||
|
||||
"""
|
||||
response = M.ImageGenerateRes()
|
||||
try:
|
||||
if not download_range(request_body_info.downloadCount):
|
||||
raise Exception(f"downloadCount is 1~4 (current value = {request_body_info.downloadCount})")
|
||||
|
||||
|
||||
args = DallEArgument(
|
||||
prompt=request_body_info.prompt,
|
||||
download_count=request_body_info.downloadCount
|
||||
)
|
||||
|
||||
info = dalle3_generate_image(args)
|
||||
|
||||
if info.get_error_messages():
|
||||
error_message = f"파일생성 error: {info.get_error_messages()}"
|
||||
LOG.error(error_message)
|
||||
return response.set_error(error=error_message, img_len=info.get_counter())
|
||||
|
||||
return response.set_message(img_len=info.get_counter())
|
||||
|
||||
except Exception as e:
|
||||
LOG.error(traceback.format_exc())
|
||||
return response.set_error(e)
|
||||
|
||||
|
||||
@router.post("/imageGenerate/bingart", summary="이미지 생성(AI) - bing art (DALL-E 3)", response_model=M.ImageGenerateRes)
|
||||
async def bing_art(request: Request, request_body_info: M.ImageGenerateReq):
|
||||
"""
|
||||
## 이미지 생성(AI) - bing art (DALL-E 3)
|
||||
> bing art를 이용하여 이미지 생성
|
||||
|
||||
### Requriements
|
||||
|
||||
|
||||
## 정보
|
||||
> 오류 발생시 오류 발생한 파일은 에러 메세지에만 남기고 저장은 안함
|
||||
> *동작 안함.
|
||||
|
||||
"""
|
||||
response = M.ImageGenerateRes()
|
||||
try:
|
||||
if not download_range(request_body_info.downloadCount):
|
||||
raise Exception(f"downloadCount is 1~4 (current value = {request_body_info.downloadCount})")
|
||||
|
||||
bing_art = BingArtGenerator()
|
||||
|
||||
info = bing_art.get_images(prompt=request_body_info.prompt,image_len=request_body_info.downloadCount)
|
||||
|
||||
return response.set_message(img_len=info)
|
||||
|
||||
except Exception as e:
|
||||
LOG.error(traceback.format_exc())
|
||||
return response.set_error(e)
|
||||
|
||||
|
||||
@router.post("/imageGenerate/imagen", summary="이미지 생성(AI) - imagen", response_model=M.ImageGenerateRes)
|
||||
async def imagen(request: Request, request_body_info: M.ImageGenerateReq):
|
||||
"""
|
||||
## 이미지 생성(AI) - imagen
|
||||
> imagen AI를 이용하여 이미지 생성
|
||||
|
||||
### Requriements
|
||||
> - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
||||
> - const.py 에 지정한 OUTPUT_FOLDER 하위에 imagen 폴더가 있어야함.
|
||||
|
||||
"""
|
||||
response = M.ImageGenerateRes()
|
||||
try:
|
||||
|
||||
if not download_range(request_body_info.downloadCount):
|
||||
raise Exception(f"downloadCount is 1~4 (current value = {request_body_info.downloadCount})")
|
||||
|
||||
img_length = imagen_generate_image(prompt=request_body_info.prompt,
|
||||
download_count=request_body_info.downloadCount
|
||||
)
|
||||
|
||||
return response.set_message(img_len=img_length)
|
||||
|
||||
except Exception as e:
|
||||
LOG.error(traceback.format_exc())
|
||||
return response.set_error(error=e)
|
||||
|
||||
|
||||
@router.post("/vactorImageSearch/imageGenerate/imagen", summary="벡터 이미지 검색 - imagen", response_model=M.ResponseBase)
|
||||
async def vactor_image(request: Request, request_body_info: M.VactorImageSearchReq):
|
||||
"""
|
||||
## 벡터 이미지 검색 - imagen
|
||||
> imagen AI를 이용하여 이미지 생성 후 vactor 검색
|
||||
|
||||
### Requriements
|
||||
> - googlecli 설치(https://cloud.google.com/sdk/docs/install?hl=ko#linux)
|
||||
> - const.py 에 지정한 OUTPUT_FOLDER 하위에 imagen 폴더가 있어야함.
|
||||
|
||||
"""
|
||||
response = M.ResponseBase()
|
||||
try:
|
||||
if request_body_info.index_type not in [M.IndexType.hnsw, M.IndexType.l2]:
|
||||
raise Exception(f"index_type is hnsw or l2 (current value = {request_body_info.index_type})")
|
||||
|
||||
img_path = imagen_generate_image_path(image_prompt=request_body_info.prompt)
|
||||
|
||||
vactor_request_data = {'quary_image_path' : img_path,'index_type' : request_body_info.index_type, 'search_num' : request_body_info.search_num}
|
||||
vactor_response = requests.post('http://localhost:51002/api/services/faiss/vactor/search', data=json.dumps(vactor_request_data))
|
||||
|
||||
if vactor_response.status_code != 200:
|
||||
raise Exception(f"response error: {json.loads(vactor_response.text)['error']}")
|
||||
|
||||
if json.loads(vactor_response.text)["error"] != None:
|
||||
raise Exception(f"vactor error: {json.loads(vactor_response.text)['error']}")
|
||||
|
||||
return response.set_message()
|
||||
|
||||
except Exception as e:
|
||||
LOG.error(traceback.format_exc())
|
||||
return response.set_error(error=e)
|
||||
298
main_rest/app/routes/users.py
Normal file
298
main_rest/app/routes/users.py
Normal file
@@ -0,0 +1,298 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
@File: users.py
|
||||
@Date: 2020-09-14
|
||||
@author: A2TEC
|
||||
@section MODIFYINFO 수정정보
|
||||
- 수정자/수정일 : 수정내역
|
||||
- 2022-01-14/hsj100@a2tec.co.kr : refactoring
|
||||
@brief: users api
|
||||
"""
|
||||
|
||||
from fastapi import APIRouter
|
||||
from starlette.requests import Request
|
||||
import bcrypt
|
||||
|
||||
from main_rest.app.common import consts
|
||||
from main_rest.app import models as M
|
||||
from main_rest.app.common.config import conf
|
||||
from main_rest.app.database.schema import Users
|
||||
from main_rest.app.database.crud import table_select, table_update, table_delete
|
||||
|
||||
from main_rest.app.utils.extra import AESCryptoCBC
|
||||
|
||||
|
||||
router = APIRouter(prefix='/user')
|
||||
|
||||
|
||||
@router.get('/me', response_model=M.UserSearchRes, summary='접속자 정보')
|
||||
async def get_me(request: Request):
|
||||
"""
|
||||
## 현재 접속된 자신정보 확인
|
||||
|
||||
***현 버전 미지원(추후 상세 처리)***
|
||||
|
||||
**결과**
|
||||
- UserSearchRes
|
||||
"""
|
||||
target_table = Users
|
||||
search_info = None
|
||||
|
||||
try:
|
||||
# request
|
||||
if conf().GLOBAL_TOKEN:
|
||||
raise Exception('not supported: use search api!')
|
||||
|
||||
accessor_info = request.state.user
|
||||
if not accessor_info:
|
||||
raise Exception('invalid accessor')
|
||||
|
||||
# search
|
||||
search_info = target_table.get(account=accessor_info.account)
|
||||
if not search_info:
|
||||
raise Exception('not found data')
|
||||
|
||||
# result
|
||||
result_info = list()
|
||||
result_info.append(M.UserInfo.from_orm(search_info))
|
||||
return M.UserSearchRes(data=result_info)
|
||||
except Exception as e:
|
||||
if search_info:
|
||||
search_info.close()
|
||||
return M.ResponseBase.set_error(str(e))
|
||||
|
||||
|
||||
@router.post('/search', response_model=M.UserSearchPagingRes, summary='유저정보 검색')
|
||||
async def user_search(request: Request, request_body_info: M.UserSearchPagingReq):
|
||||
"""
|
||||
## 유저정보 검색 (기본)
|
||||
검색 조건은 유저 테이블 항목만 가능 (Request body: Schema 참조)\n
|
||||
관련 정보 연동 검색은 별도 API 사용
|
||||
|
||||
**세부항목**
|
||||
- **paging**\n
|
||||
항목 미사용시에는 페이징기능 없이 검색조건(search) 결과 모두 반환
|
||||
|
||||
- **search**\n
|
||||
검색에 필요한 항목들을 search 에 포함시킨다.\n
|
||||
검색에 사용된 각 항목들은 AND 조건으로 처리된다.
|
||||
|
||||
- **전체검색**\n
|
||||
empty object 사용 ( {} )\n
|
||||
예) "search": {}
|
||||
|
||||
- **검색항목**\n
|
||||
- 부분검색 항목\n
|
||||
SQL 문법( %, _ )을 사용한다.\n
|
||||
__like: 시작포함(X%), 중간포함(%X%), 끝포함(%X)
|
||||
- 구간검색 항목
|
||||
* __lt: 주어진 값보다 작은값
|
||||
* __lte: 주어진 값보다 같거나 작은 값
|
||||
* __gt: 주어진 값보다 큰값
|
||||
* __gte: 주어진 값보다 같거나 큰값
|
||||
|
||||
**결과**
|
||||
- UserSearchPagingRes
|
||||
"""
|
||||
return await table_select(request.state.user, Users, request_body_info, M.UserSearchPagingRes, M.UserInfo)
|
||||
|
||||
|
||||
@router.put('/update', response_model=M.ResponseBase, summary='유저정보 변경')
|
||||
async def user_update(request: Request, request_body_info: M.UserUpdateMultiReq):
|
||||
"""
|
||||
## 유저정보 변경
|
||||
|
||||
**search_info**: 변경대상\n
|
||||
|
||||
**update_info**: 변경내용\n
|
||||
- **비밀번호** 제외
|
||||
|
||||
**결과**
|
||||
- ResponseBase
|
||||
"""
|
||||
return await table_update(request.state.user, Users, request_body_info, M.ResponseBase)
|
||||
|
||||
|
||||
@router.put('/update_pw', response_model=M.ResponseBase, summary='유저 비밀번호 변경')
|
||||
async def user_update_pw(request: Request, request_body_info: M.UserUpdatePWReq):
|
||||
"""
|
||||
## 유저정보 비밀번호 변경
|
||||
|
||||
**account**의 **비밀번호**를 변경한다.
|
||||
|
||||
**결과**
|
||||
- ResponseBase
|
||||
"""
|
||||
target_table = Users
|
||||
search_info = None
|
||||
|
||||
try:
|
||||
# request
|
||||
accessor_info = request.state.user
|
||||
if not accessor_info:
|
||||
raise Exception('invalid accessor')
|
||||
if not request_body_info.account:
|
||||
raise Exception('invalid account')
|
||||
|
||||
# decrypt pw
|
||||
try:
|
||||
decode_cur_pw = request_body_info.current_pw.encode('utf-8')
|
||||
desc_cur_pw = AESCryptoCBC().decrypt(decode_cur_pw)
|
||||
except Exception as e:
|
||||
raise Exception(f'failed decryption [current_pw]: {e}')
|
||||
try:
|
||||
decode_new_pw = request_body_info.new_pw.encode('utf-8')
|
||||
desc_new_pw = AESCryptoCBC().decrypt(decode_new_pw)
|
||||
except Exception as e:
|
||||
raise Exception(f'failed decryption [new_pw]: {e}')
|
||||
|
||||
# search
|
||||
target_user = target_table.get(account=request_body_info.account)
|
||||
is_verified = bcrypt.checkpw(desc_cur_pw, target_user.pw.encode('utf-8'))
|
||||
if not is_verified:
|
||||
raise Exception('invalid password')
|
||||
|
||||
search_info = target_table.filter(id=target_user.id)
|
||||
if not search_info.first():
|
||||
raise Exception('not found data')
|
||||
|
||||
# process
|
||||
hash_pw = bcrypt.hashpw(desc_new_pw, bcrypt.gensalt())
|
||||
result_info = search_info.update(auto_commit=True, pw=hash_pw)
|
||||
if not result_info or not result_info.id:
|
||||
raise Exception('failed update')
|
||||
|
||||
# result
|
||||
return M.ResponseBase()
|
||||
except Exception as e:
|
||||
if search_info:
|
||||
search_info.close()
|
||||
return M.ResponseBase.set_error(str(e))
|
||||
|
||||
|
||||
@router.delete('/delete', response_model=M.ResponseBase, summary='유저정보 삭제')
|
||||
async def user_delete(request: Request, request_body_info: M.UserSearchReq):
|
||||
"""
|
||||
## 유저정보 삭제
|
||||
조건에 해당하는 정보를 모두 삭제한다.\n
|
||||
- **본 API는 DB에서 완적삭제를 하는 함수이며, 서버관리자가 사용하는 것을 권장한다.**
|
||||
- **update API를 사용하여 상태 항목을 변경해서 사용하는 것을 권장.**
|
||||
|
||||
`유저삭제시 관계 테이블의 정보도 같이 삭제된다.`
|
||||
|
||||
**결과**
|
||||
- ResponseBase
|
||||
"""
|
||||
return await table_delete(request.state.user, Users, request_body_info, M.ResponseBase)
|
||||
|
||||
|
||||
# NOTE(hsj100): apikey
|
||||
"""
|
||||
"""
|
||||
# @router.get('/apikeys', response_model=List[M.GetApiKeyList])
|
||||
# async def get_api_keys(request: Request):
|
||||
# """
|
||||
# API KEY 조회
|
||||
# :param request:
|
||||
# :return:
|
||||
# """
|
||||
# user = request.state.user
|
||||
# api_keys = ApiKeys.filter(user_id=user.id).all()
|
||||
# return api_keys
|
||||
#
|
||||
#
|
||||
# @router.post('/apikeys', response_model=M.GetApiKeys)
|
||||
# async def create_api_keys(request: Request, key_info: M.AddApiKey, session: Session = Depends(db.session)):
|
||||
# """
|
||||
# API KEY 생성
|
||||
# :param request:
|
||||
# :param key_info:
|
||||
# :param session:
|
||||
# :return:
|
||||
# """
|
||||
# user = request.state.user
|
||||
#
|
||||
# api_keys = ApiKeys.filter(session, user_id=user.id, status='active').count()
|
||||
# if api_keys == MAX_API_KEY:
|
||||
# raise ex.MaxKeyCountEx()
|
||||
#
|
||||
# alphabet = string.ascii_letters + string.digits
|
||||
# s_key = ''.join(secrets.choice(alphabet) for _ in range(40))
|
||||
# uid = None
|
||||
# while not uid:
|
||||
# uid_candidate = f'{str(uuid4())[:-12]}{str(uuid4())}'
|
||||
# uid_check = ApiKeys.get(access_key=uid_candidate)
|
||||
# if not uid_check:
|
||||
# uid = uid_candidate
|
||||
#
|
||||
# key_info = key_info.dict()
|
||||
# new_key = ApiKeys.create(session, auto_commit=True, secret_key=s_key, user_id=user.id, access_key=uid, **key_info)
|
||||
# return new_key
|
||||
#
|
||||
#
|
||||
# @router.put('/apikeys/{key_id}', response_model=M.GetApiKeyList)
|
||||
# async def update_api_keys(request: Request, key_id: int, key_info: M.AddApiKey):
|
||||
# """
|
||||
# API KEY User Memo Update
|
||||
# :param request:
|
||||
# :param key_id:
|
||||
# :param key_info:
|
||||
# :return:
|
||||
# """
|
||||
# user = request.state.user
|
||||
# key_data = ApiKeys.filter(id=key_id)
|
||||
# if key_data and key_data.first().user_id == user.id:
|
||||
# return key_data.update(auto_commit=True, **key_info.dict())
|
||||
# raise ex.NoKeyMatchEx()
|
||||
#
|
||||
#
|
||||
# @router.delete('/apikeys/{key_id}')
|
||||
# async def delete_api_keys(request: Request, key_id: int, access_key: str):
|
||||
# user = request.state.user
|
||||
# await check_api_owner(user.id, key_id)
|
||||
# search_by_key = ApiKeys.filter(access_key=access_key)
|
||||
# if not search_by_key.first():
|
||||
# raise ex.NoKeyMatchEx()
|
||||
# search_by_key.delete(auto_commit=True)
|
||||
# return MessageOk()
|
||||
#
|
||||
#
|
||||
# @router.get('/apikeys/{key_id}/whitelists', response_model=List[M.GetAPIWhiteLists])
|
||||
# async def get_api_keys(request: Request, key_id: int):
|
||||
# user = request.state.user
|
||||
# await check_api_owner(user.id, key_id)
|
||||
# whitelists = ApiWhiteLists.filter(api_key_id=key_id).all()
|
||||
# return whitelists
|
||||
#
|
||||
#
|
||||
# @router.post('/apikeys/{key_id}/whitelists', response_model=M.GetAPIWhiteLists)
|
||||
# async def create_api_keys(request: Request, key_id: int, ip: M.CreateAPIWhiteLists, session: Session = Depends(db.session)):
|
||||
# user = request.state.user
|
||||
# await check_api_owner(user.id, key_id)
|
||||
# import ipaddress
|
||||
# try:
|
||||
# _ip = ipaddress.ip_address(ip.ip_addr)
|
||||
# except Exception as e:
|
||||
# raise ex.InvalidIpEx(ip.ip_addr, e)
|
||||
# if ApiWhiteLists.filter(api_key_id=key_id).count() == MAX_API_WHITELIST:
|
||||
# raise ex.MaxWLCountEx()
|
||||
# ip_dup = ApiWhiteLists.get(api_key_id=key_id, ip_addr=ip.ip_addr)
|
||||
# if ip_dup:
|
||||
# return ip_dup
|
||||
# ip_reg = ApiWhiteLists.create(session=session, auto_commit=True, api_key_id=key_id, ip_addr=ip.ip_addr)
|
||||
# return ip_reg
|
||||
#
|
||||
#
|
||||
# @router.delete('/apikeys/{key_id}/whitelists/{list_id}')
|
||||
# async def delete_api_keys(request: Request, key_id: int, list_id: int):
|
||||
# user = request.state.user
|
||||
# await check_api_owner(user.id, key_id)
|
||||
# ApiWhiteLists.filter(id=list_id, api_key_id=key_id).delete()
|
||||
#
|
||||
# return MessageOk()
|
||||
#
|
||||
#
|
||||
# async def check_api_owner(user_id, key_id):
|
||||
# api_keys = ApiKeys.get(id=key_id, user_id=user_id)
|
||||
# if not api_keys:
|
||||
# raise ex.NoKeyMatchEx()
|
||||
Reference in New Issue
Block a user