152 lines
5.1 KiB
Python
152 lines
5.1 KiB
Python
from typing import Tuple, Dict
|
||
|
||
from sqlalchemy.orm import sessionmaker
|
||
from sqlalchemy import Engine, text, update
|
||
|
||
from s3 import s3helper
|
||
from db import pgclass
|
||
|
||
class DB:
|
||
_engine = None
|
||
|
||
@classmethod
|
||
def __init__(cls, engine):
|
||
cls._engine:Engine = engine
|
||
|
||
@classmethod
|
||
def getsession(cls):
|
||
Session = sessionmaker(bind=cls._engine)
|
||
return Session()
|
||
|
||
db:DB = None
|
||
|
||
|
||
# role (general) (owner) (admin)
|
||
# 獲取單一文章
|
||
def solo_article_fetcher(role:str, key:int, hash:str=None) -> Tuple[Dict, int]: # admin, owner, general
|
||
with db.getsession() as session:
|
||
# article fetch
|
||
stmt="SELECT posts.id, posts.content, posts.file_list, meta.igid, posts.hash, meta.ip, pmark.mark " \
|
||
+"FROM posts " \
|
||
+"INNER JOIN mark AS pmark ON posts.hash=pmark.hash " \
|
||
+"INNER JOIN article_meta AS meta ON posts.hash=meta.hash "
|
||
if role == "owner": # 驗證id/hash,可以看到本體(無驗證)
|
||
stmt += "WHERE posts.id = :id AND posts.hash = :hash"
|
||
elif role == "admin": # 驗證id,可以看到本體(無驗證)
|
||
stmt += "WHERE posts.id = :id"
|
||
elif role == "general": # 驗證id,可以看到本體(visible)
|
||
stmt += "WHERE posts.id=:id AND pmark.mark='visible'"
|
||
result = session.execute(text(stmt), {"id":key, "hash":hash})
|
||
res = result.first()
|
||
if res is None:
|
||
return {}, 404
|
||
|
||
# comment fetch
|
||
stmt="SELECT c.sha1 " \
|
||
+"FROM posts " \
|
||
+"INNER JOIN unnest(posts.comment_list) AS c ON c=ANY(posts.comment_list) " \
|
||
+"INNER JOIN mark AS cmark ON c.hash=cmark.hash " \
|
||
+"WHERE posts.id=:id"
|
||
if role == "general": # 留言sha1(visible)
|
||
stmt+=" AND cmark.mark='visible'"
|
||
result = session.execute(text(stmt), {"id":res[0]})
|
||
cres = result.all()
|
||
|
||
# mapping
|
||
one = {
|
||
"id": res[0],
|
||
"content": res[1],
|
||
"igid": res[3],
|
||
}
|
||
if res[2]: # files
|
||
one["files_hash"] = res[2]
|
||
if res[4]: # comments
|
||
one["comments_hash"] = [ c[0] for c in cres ]
|
||
|
||
if role == "admin":
|
||
one["ip"] = res[5]
|
||
one["mark"] = res[6]
|
||
one["hash"] = res[4]
|
||
|
||
return one, 200
|
||
|
||
|
||
# role (general) (owner) (admin)
|
||
# 獲取單一留言 - 可能不會用到
|
||
def solo_comment_fetcher(role:str, key:str, hash:str=None) -> Tuple[Dict, int]: # admin, owner, general
|
||
with db.getsession() as session:
|
||
# query
|
||
stmt="SELECT posts.id AS parent_id, posts.hash AS parent_hash, pmark.mark AS parent_mark, cmark.mark AS comment_mark, c.* " \
|
||
+"FROM posts " \
|
||
+"INNER JOIN unnest(posts.comment_list) AS c ON c=ANY(posts.comment_list) " \
|
||
+"JOIN mark AS pmark ON posts.hash=pmark.hash " \
|
||
+"JOIN mark AS cmark ON c.hash=cmark.hash " \
|
||
+"WHERE c.sha1=:sha1 "
|
||
if role == "general":
|
||
# 對一般用戶,sha1查詢,確保本體跟留言可見
|
||
stmt += "AND pmark.mark='visible' AND cmark.mark='visible'"
|
||
arta = session.execute(text(stmt), {'sha1':key}).first()
|
||
elif role == "owner":
|
||
# 對發文者,sha1查詢,sha256查詢,不設檢查
|
||
stmt += "AND c.hash=:hash"
|
||
arta = session.execute(text(stmt), {'sha1':key, 'hash':hash}).first()
|
||
elif role == "admin":
|
||
# 對管理員,sha1查詢,不設檢查
|
||
arta = session.execute(text(stmt), {'sha1':key}).first()
|
||
if arta is None:
|
||
return {}, 404
|
||
|
||
# mapping
|
||
one = {
|
||
"content": arta[4],
|
||
"sha1": arta[8]
|
||
}
|
||
|
||
if role == "admin":
|
||
one["ip"] = arta[5]
|
||
one["mark"] = arta[3]
|
||
one["hash"] = arta[6]
|
||
|
||
return one, 200
|
||
|
||
|
||
# 獲取檔案 - for IG
|
||
def solo_file_fetcher(role:str, fnhash:str) -> Tuple[dict, int]: # general, admin
|
||
with db.getsession() as session:
|
||
arta="SELECT posts.id FROM posts " \
|
||
+"INNER JOIN mark ON posts.hash=mark.hash " \
|
||
+"WHERE :fnhash=ANY (posts.file_list) "
|
||
if role == "general":
|
||
arta += "AND mark.mark = 'visible'"
|
||
arta = session.execute(text(arta), {'fnhash':fnhash}).first()
|
||
if arta is None: # 檢查文章本體是否存在/可以閱覽
|
||
return {}, 404
|
||
|
||
# fetch file
|
||
f, err = s3helper.solo_file_fetcher(fnhash)
|
||
if err:
|
||
return {}, 404
|
||
return f, 200
|
||
|
||
|
||
# 填入 igid
|
||
def solo_article_set_igid(id:int, igid:str) -> int:
|
||
# get hash
|
||
article, code = solo_article_fetcher(role="admin", key=id)
|
||
if code != 200:
|
||
return 1
|
||
hash = article["hash"]
|
||
# print(hash)
|
||
|
||
# edit igid
|
||
err = 0
|
||
article_meta = pgclass.SQLmeta
|
||
with db.getsession() as session:
|
||
try:
|
||
stmt = update(article_meta).where(article_meta.hash==hash).values(igid=igid)
|
||
session.execute(stmt)
|
||
except Exception as e:
|
||
err = 1
|
||
session.commit()
|
||
return err
|