404
This commit is contained in:
parent
a548599662
commit
34fe546cd6
@ -4,12 +4,12 @@ import math
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
import jwt
|
import jwt
|
||||||
from flask import Blueprint, request, jsonify, make_response, g
|
from flask import Blueprint, request, jsonify, make_response, g, abort
|
||||||
from bcrypt import hashpw, gensalt, checkpw
|
from bcrypt import hashpw, gensalt, checkpw
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
from utils import pgclass, setting_loader, logger
|
from utils import pgclass, setting_loader, logger
|
||||||
from utils.misc import error, internal_json2protobuf, error_proto
|
from utils.misc import error, internal_json2protobuf
|
||||||
from utils.dbhelper import db, solo_article_fetcher, multi_article_fetcher, solo_file_fetcher, solo_article_remover
|
from utils.dbhelper import db, solo_article_fetcher, multi_article_fetcher, solo_file_fetcher, solo_article_remover
|
||||||
from utils.platform_consts import PLIST, PLIST_ROOT
|
from utils.platform_consts import PLIST, PLIST_ROOT
|
||||||
from protobuf_files import niming_pb2
|
from protobuf_files import niming_pb2
|
||||||
@ -204,7 +204,6 @@ def article_del(id:int):
|
|||||||
logger.logger("article.delete", "User:%s deleted post (id=%d): last_status=%s"%(opuser.user, result["id"], result["mark"]))
|
logger.logger("article.delete", "User:%s deleted post (id=%d): last_status=%s"%(opuser.user, result["id"], result["mark"]))
|
||||||
|
|
||||||
return niming_pb2.FetchResponse(
|
return niming_pb2.FetchResponse(
|
||||||
status = niming_pb2.Status.Success,
|
|
||||||
posts = [ niming_pb2.FetchResponse.Message(id = result["id"], mark = result["mark"]) ]
|
posts = [ niming_pb2.FetchResponse.Message(id = result["id"], mark = result["mark"]) ]
|
||||||
).SerializeToString(), 200
|
).SerializeToString(), 200
|
||||||
|
|
||||||
@ -216,20 +215,20 @@ def article_pend(id:int):
|
|||||||
with db.getsession() as session:
|
with db.getsession() as session:
|
||||||
# 確保文章存在
|
# 確保文章存在
|
||||||
res = session.query(table).filter(table.id==int(id)).first()
|
res = session.query(table).filter(table.id==int(id)).first()
|
||||||
if res is None: return error_proto("fetch", "Post not found"), 404
|
if res is None: return abort(404)
|
||||||
|
|
||||||
# 如果文章已經公開
|
# 如果文章已經公開
|
||||||
if res.mark == "visible":
|
if res.mark == "visible":
|
||||||
return error_proto("fetch", "Post is already visible."), 400
|
return abort(400)
|
||||||
elif res.mark == "pending":
|
elif res.mark == "pending":
|
||||||
res.mark = "visible"
|
res.mark = "visible"
|
||||||
session.commit()
|
session.commit()
|
||||||
|
|
||||||
# run IG Post
|
# run IG Post
|
||||||
|
|
||||||
return niming_pb2.FetchResponse(status=niming_pb2.Status.Success).SerializeToString(), 200
|
return abort(200)
|
||||||
else:
|
else:
|
||||||
return error_proto("fetch", "Post mark error"), 500
|
return abort(500)
|
||||||
|
|
||||||
####################
|
####################
|
||||||
# Setting Area #
|
# Setting Area #
|
||||||
|
@ -3,12 +3,12 @@ import hashlib
|
|||||||
import secrets
|
import secrets
|
||||||
|
|
||||||
import magic
|
import magic
|
||||||
from flask import Blueprint, request, jsonify
|
from flask import Blueprint, request, abort
|
||||||
from google.protobuf.message import DecodeError
|
from google.protobuf.message import DecodeError
|
||||||
|
|
||||||
from utils import logger, pgclass, setting_loader
|
from utils import logger, pgclass, setting_loader
|
||||||
from utils.dbhelper import db, solo_article_fetcher, multi_article_fetcher, solo_file_fetcher, solo_article_remover
|
from utils.dbhelper import db, solo_article_fetcher, multi_article_fetcher, solo_file_fetcher, solo_article_remover
|
||||||
from utils.misc import error, error_proto, internal_json2protobuf
|
from utils.misc import error, internal_json2protobuf
|
||||||
from protobuf_files import niming_pb2
|
from protobuf_files import niming_pb2
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -62,7 +62,6 @@ def owner_getarticle(id:int):
|
|||||||
logger.logger("delpost", "Delete post (id=%d): last_status=%s"
|
logger.logger("delpost", "Delete post (id=%d): last_status=%s"
|
||||||
%(result["id"], str(result["mark"])))
|
%(result["id"], str(result["mark"])))
|
||||||
return niming_pb2.FetchResponse(
|
return niming_pb2.FetchResponse(
|
||||||
status = niming_pb2.Status.Success,
|
|
||||||
posts = [ niming_pb2.FetchResponse.Message(id = result["id"], mark = result["mark"]) ]
|
posts = [ niming_pb2.FetchResponse.Message(id = result["id"], mark = result["mark"]) ]
|
||||||
).SerializeToString(), 200
|
).SerializeToString(), 200
|
||||||
|
|
||||||
@ -88,12 +87,12 @@ def posting():
|
|||||||
# protobuf parse
|
# protobuf parse
|
||||||
recv = niming_pb2.Post()
|
recv = niming_pb2.Post()
|
||||||
try: recv.ParseFromString(request.data)
|
try: recv.ParseFromString(request.data)
|
||||||
except DecodeError: return error_proto("post", "Protobuf decode error"), 400
|
except DecodeError: return abort(400)
|
||||||
|
|
||||||
# content and check
|
# content and check
|
||||||
ctx = str(recv.content)
|
ctx = str(recv.content)
|
||||||
if len(ctx) == 0 or len(ctx) > maxword: # length check
|
if len(ctx) == 0 or len(ctx) > maxword: # length check
|
||||||
return error_proto("post", "no content or too many words"), 400
|
return abort(400)
|
||||||
|
|
||||||
# hash
|
# hash
|
||||||
seed = ctx + str(time.time()) + str(secrets.token_urlsafe(nbytes=16))
|
seed = ctx + str(time.time()) + str(secrets.token_urlsafe(nbytes=16))
|
||||||
@ -105,7 +104,7 @@ def posting():
|
|||||||
# 檢查指向的文章是否也是留言
|
# 檢查指向的文章是否也是留言
|
||||||
reftg, code = solo_article_fetcher(role="general", key=ref)
|
reftg, code = solo_article_fetcher(role="general", key=ref)
|
||||||
if code != 200 or reftg["reference"]:
|
if code != 200 or reftg["reference"]:
|
||||||
return error_proto("post", "Invalid Reference"), 400
|
return abort(400)
|
||||||
else:
|
else:
|
||||||
ref = None
|
ref = None
|
||||||
|
|
||||||
@ -114,16 +113,16 @@ def posting():
|
|||||||
# check - size
|
# check - size
|
||||||
atts = opt["Attachment_Count"]
|
atts = opt["Attachment_Count"]
|
||||||
sizelimit = opt["Attachment_Size"]
|
sizelimit = opt["Attachment_Size"]
|
||||||
if len(files) > atts: return error_proto("post", "Too many files"), 400
|
if len(files) > atts: return abort(400)
|
||||||
for f in files:
|
for f in files:
|
||||||
if len(f) <= 0 or len(f) > sizelimit: return error_proto("post", "File size error"), 400
|
if len(f) <= 0 or len(f) > sizelimit: return abort(400)
|
||||||
# check - mimetype
|
# check - mimetype
|
||||||
allowed_mime = opt["Allowed_MIME"]
|
allowed_mime = opt["Allowed_MIME"]
|
||||||
fmimes = []
|
fmimes = []
|
||||||
for f in files:
|
for f in files:
|
||||||
mime = magic.Magic(mime=True)
|
mime = magic.Magic(mime=True)
|
||||||
type = mime.from_buffer(f)
|
type = mime.from_buffer(f)
|
||||||
if not(type in allowed_mime): return error_proto("post", "File format error"), 400
|
if not(type in allowed_mime): return abort(400)
|
||||||
fmimes.append(type)
|
fmimes.append(type)
|
||||||
|
|
||||||
# IP
|
# IP
|
||||||
@ -163,14 +162,13 @@ def posting():
|
|||||||
session.commit() # second commit
|
session.commit() # second commit
|
||||||
result_id = data.id
|
result_id = data.id
|
||||||
except:
|
except:
|
||||||
return error_proto("post", "Create new post failed"), 400
|
return abort(400)
|
||||||
|
|
||||||
# logger
|
# logger
|
||||||
logger.logger("newpost", "New post (id=%d point to %s): %s"%(result_id, ref, mark))
|
logger.logger("newpost", "New post (id=%d point to %s): %s"%(result_id, ref, mark))
|
||||||
|
|
||||||
# to protobuf & return
|
# to protobuf & return
|
||||||
proto_stres = niming_pb2.PostResponse(
|
proto_stres = niming_pb2.PostResponse(
|
||||||
status = niming_pb2.Status.Success,
|
|
||||||
hash = hash,
|
hash = hash,
|
||||||
id = int(result_id)
|
id = int(result_id)
|
||||||
).SerializeToString()
|
).SerializeToString()
|
||||||
|
@ -37,7 +37,5 @@ message FetchResponse {
|
|||||||
repeated uint64 comments_id = 9;
|
repeated uint64 comments_id = 9;
|
||||||
}
|
}
|
||||||
// Several post info
|
// Several post info
|
||||||
Status status = 1;
|
repeated Message posts = 1;
|
||||||
repeated Message posts = 2;
|
|
||||||
optional string failed_message = 3;
|
|
||||||
}
|
}
|
@ -13,21 +13,21 @@ _sym_db = _symbol_database.Default()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cniming.proto\"@\n\x04Post\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x03ref\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12\r\n\x05\x66iles\x18\x03 \x03(\x0c\x42\x06\n\x04_ref\"q\n\x0cPostResponse\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\x12\x0c\n\x04hash\x18\x02 \x01(\t\x12\n\n\x02id\x18\x03 \x01(\x04\x12\x1b\n\x0e\x66\x61iled_message\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x11\n\x0f_failed_message\"\xb9\x02\n\rFetchResponse\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\x12%\n\x05posts\x18\x02 \x03(\x0b\x32\x16.FetchResponse.Message\x12\x1b\n\x0e\x66\x61iled_message\x18\x03 \x01(\tH\x00\x88\x01\x01\x1a\xb7\x01\n\x07Message\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12\x10\n\x03ref\x18\x03 \x01(\x04H\x00\x88\x01\x01\x12\x10\n\x08\x66iles_id\x18\x04 \x03(\x04\x12\x11\n\x04hash\x18\x05 \x01(\tH\x01\x88\x01\x01\x12\x0c\n\x04igid\x18\x06 \x01(\t\x12\x0c\n\x04mark\x18\x07 \x01(\t\x12\x0f\n\x02ip\x18\x08 \x01(\tH\x02\x88\x01\x01\x12\x13\n\x0b\x63omments_id\x18\t \x03(\x04\x42\x06\n\x04_refB\x07\n\x05_hashB\x05\n\x03_ipB\x11\n\x0f_failed_message*!\n\x06Status\x12\n\n\x06\x46\x61iled\x10\x00\x12\x0b\n\x07Success\x10\x01\x62\x06proto3')
|
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cniming.proto\"@\n\x04Post\x12\x0f\n\x07\x63ontent\x18\x01 \x01(\t\x12\x10\n\x03ref\x18\x02 \x01(\x03H\x00\x88\x01\x01\x12\r\n\x05\x66iles\x18\x03 \x03(\x0c\x42\x06\n\x04_ref\"q\n\x0cPostResponse\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\x12\x0c\n\x04hash\x18\x02 \x01(\t\x12\n\n\x02id\x18\x03 \x01(\x04\x12\x1b\n\x0e\x66\x61iled_message\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x11\n\x0f_failed_message\"\xf0\x01\n\rFetchResponse\x12%\n\x05posts\x18\x01 \x03(\x0b\x32\x16.FetchResponse.Message\x1a\xb7\x01\n\x07Message\x12\n\n\x02id\x18\x01 \x01(\x04\x12\x0f\n\x07\x63ontent\x18\x02 \x01(\t\x12\x10\n\x03ref\x18\x03 \x01(\x04H\x00\x88\x01\x01\x12\x10\n\x08\x66iles_id\x18\x04 \x03(\x04\x12\x11\n\x04hash\x18\x05 \x01(\tH\x01\x88\x01\x01\x12\x0c\n\x04igid\x18\x06 \x01(\t\x12\x0c\n\x04mark\x18\x07 \x01(\t\x12\x0f\n\x02ip\x18\x08 \x01(\tH\x02\x88\x01\x01\x12\x13\n\x0b\x63omments_id\x18\t \x03(\x04\x42\x06\n\x04_refB\x07\n\x05_hashB\x05\n\x03_ip*!\n\x06Status\x12\n\n\x06\x46\x61iled\x10\x00\x12\x0b\n\x07Success\x10\x01\x62\x06proto3')
|
||||||
|
|
||||||
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
|
||||||
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'niming_pb2', globals())
|
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'niming_pb2', globals())
|
||||||
if _descriptor._USE_C_DESCRIPTORS == False:
|
if _descriptor._USE_C_DESCRIPTORS == False:
|
||||||
|
|
||||||
DESCRIPTOR._options = None
|
DESCRIPTOR._options = None
|
||||||
_STATUS._serialized_start=513
|
_STATUS._serialized_start=440
|
||||||
_STATUS._serialized_end=546
|
_STATUS._serialized_end=473
|
||||||
_POST._serialized_start=16
|
_POST._serialized_start=16
|
||||||
_POST._serialized_end=80
|
_POST._serialized_end=80
|
||||||
_POSTRESPONSE._serialized_start=82
|
_POSTRESPONSE._serialized_start=82
|
||||||
_POSTRESPONSE._serialized_end=195
|
_POSTRESPONSE._serialized_end=195
|
||||||
_FETCHRESPONSE._serialized_start=198
|
_FETCHRESPONSE._serialized_start=198
|
||||||
_FETCHRESPONSE._serialized_end=511
|
_FETCHRESPONSE._serialized_end=438
|
||||||
_FETCHRESPONSE_MESSAGE._serialized_start=309
|
_FETCHRESPONSE_MESSAGE._serialized_start=255
|
||||||
_FETCHRESPONSE_MESSAGE._serialized_end=492
|
_FETCHRESPONSE_MESSAGE._serialized_end=438
|
||||||
# @@protoc_insertion_point(module_scope)
|
# @@protoc_insertion_point(module_scope)
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
from typing import Tuple, Dict, List
|
from typing import Tuple, Dict, List
|
||||||
|
|
||||||
from flask import make_response, Response, jsonify
|
from flask import make_response, Response, abort
|
||||||
from sqlalchemy.orm import sessionmaker, aliased
|
from sqlalchemy.orm import sessionmaker, aliased
|
||||||
from sqlalchemy import desc, func, literal, and_
|
from sqlalchemy import desc, func, literal, and_
|
||||||
|
|
||||||
from utils import pgclass
|
from utils import pgclass
|
||||||
from utils.misc import error, error_proto
|
from utils.misc import error
|
||||||
from protobuf_files import niming_pb2
|
from protobuf_files import niming_pb2
|
||||||
|
|
||||||
class db:
|
class db:
|
||||||
@ -23,7 +23,7 @@ class db:
|
|||||||
|
|
||||||
# role (general) (owner) (admin)
|
# role (general) (owner) (admin)
|
||||||
# 獲取單一文章
|
# 獲取單一文章
|
||||||
def solo_article_fetcher(role:str, key) -> Tuple[Dict | bytes, int]: # admin, owner, general
|
def solo_article_fetcher(role:str, key) -> Tuple[Dict, int]: # admin, owner, general
|
||||||
table = pgclass.SQLarticle # main
|
table = pgclass.SQLarticle # main
|
||||||
table2 = aliased(table) # comment
|
table2 = aliased(table) # comment
|
||||||
with db.getsession() as session:
|
with db.getsession() as session:
|
||||||
@ -51,7 +51,7 @@ def solo_article_fetcher(role:str, key) -> Tuple[Dict | bytes, int]: # admin, ow
|
|||||||
res = res.group_by(table.id, table.content, table.reference, table.file_list,
|
res = res.group_by(table.id, table.content, table.reference, table.file_list,
|
||||||
table.hash, table.igid, table.mark, table.ip).first()
|
table.hash, table.igid, table.mark, table.ip).first()
|
||||||
if res is None:
|
if res is None:
|
||||||
return error_proto("fetch", "Post not found"), 404
|
return abort(404)
|
||||||
|
|
||||||
# mapping
|
# mapping
|
||||||
one = {
|
one = {
|
||||||
@ -76,13 +76,11 @@ def solo_article_fetcher(role:str, key) -> Tuple[Dict | bytes, int]: # admin, ow
|
|||||||
def multi_article_fetcher(role:str, page:str, count:int) -> Tuple[bytes, int]: # general, admin
|
def multi_article_fetcher(role:str, page:str, count:int) -> Tuple[bytes, int]: # general, admin
|
||||||
# checker
|
# checker
|
||||||
if page is None or not page.isdigit():
|
if page is None or not page.isdigit():
|
||||||
return error_proto("fetch", "Arguments error"), 400
|
return abort(400)
|
||||||
page = int(page)*count
|
page = int(page)*count
|
||||||
|
|
||||||
table = pgclass.SQLarticle
|
table = pgclass.SQLarticle
|
||||||
resfn = niming_pb2.FetchResponse(
|
resfn = niming_pb2.FetchResponse()
|
||||||
status = niming_pb2.Status.Success
|
|
||||||
)
|
|
||||||
|
|
||||||
with db.getsession() as session:
|
with db.getsession() as session:
|
||||||
# query
|
# query
|
||||||
@ -112,7 +110,7 @@ def multi_article_fetcher(role:str, page:str, count:int) -> Tuple[bytes, int]: #
|
|||||||
|
|
||||||
|
|
||||||
# 刪除文章
|
# 刪除文章
|
||||||
def solo_article_remover(role:str, hash:str=None, id:int=None) -> Tuple[Dict | bytes, int]: # admin, owner
|
def solo_article_remover(role:str, hash:str=None, id:int=None) -> Tuple[Dict, int]: # admin, owner
|
||||||
key = None
|
key = None
|
||||||
if role == "admin": key = id
|
if role == "admin": key = id
|
||||||
elif role == "owner": key = (hash, id)
|
elif role == "owner": key = (hash, id)
|
||||||
@ -125,7 +123,7 @@ def solo_article_remover(role:str, hash:str=None, id:int=None) -> Tuple[Dict | b
|
|||||||
elif role == "owner":
|
elif role == "owner":
|
||||||
res = session.query(table).filter(table.hash == key[0], table.id == key[1]).first()
|
res = session.query(table).filter(table.hash == key[0], table.id == key[1]).first()
|
||||||
if res is None: # 檢查本體是否存在
|
if res is None: # 檢查本體是否存在
|
||||||
return error_proto("fetch", "Post not found!"), 404
|
return abort(404)
|
||||||
# 刪本體
|
# 刪本體
|
||||||
session.delete(res)
|
session.delete(res)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
@ -6,18 +6,6 @@ def error(message:str) -> Response:
|
|||||||
return jsonify({"error":message})
|
return jsonify({"error":message})
|
||||||
|
|
||||||
|
|
||||||
def error_proto(type:str, message:str) -> Response:
|
|
||||||
if type == "post":
|
|
||||||
proto = niming_pb2.PostResponse()
|
|
||||||
proto.hash = ""
|
|
||||||
proto.id = 0
|
|
||||||
elif type == "fetch":
|
|
||||||
proto = niming_pb2.FetchResponse()
|
|
||||||
proto.status = niming_pb2.Status.Failed
|
|
||||||
proto.failed_message = message
|
|
||||||
return proto.SerializeToString()
|
|
||||||
|
|
||||||
|
|
||||||
def internal_json2protobuf(original:list|dict) -> bytes:
|
def internal_json2protobuf(original:list|dict) -> bytes:
|
||||||
if isinstance(original, dict):
|
if isinstance(original, dict):
|
||||||
original = [original]
|
original = [original]
|
||||||
|
Loading…
Reference in New Issue
Block a user