Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,21 @@
services_path='services'
if not os.path.exists(services_path):
logger.critical(f"{os.path.join(os.getcwd(),services_path)} 不存在")
raise
raise OSError(f"{os.path.join(os.getcwd(),services_path)} 不存在")

services = os.listdir(services_path)
for service in services:
try:
entrypoint = importlib.import_module(f"{services_path}.{service}").entrypoint
matedata = entrypoint(settings)
metadata = entrypoint(settings)
logger.warn("#"*50+f"""
加载{service}
\t作者{matedata['Author']}
\t版本{matedata['Version']}
\t描述{matedata['Describe']}
\t作者{metadata['Author']}
\t版本{metadata['Version']}
\t描述{metadata['Describe']}
"""+"#"*50)
application.include_router(matedata['Router'])
matedata['Init']()
application.include_router(metadata['Router'])
metadata['Init']()
except Exception as e:
logger.warn(f"加载{service}出错")
logger.warn(e)
Expand Down
31 changes: 31 additions & 0 deletions services/verify/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""

"""

from fastapi import APIRouter
from dynaconf import Dynaconf

from . import router

router.init(APIRouter(prefix="/verify"), APIRouter(prefix="/verify"))


def entrypoint(settings: Dynaconf):
return {
"Author": "Bernie H.",
"Version": "1.0.0",
"Describe": "验证微服务,主要用于验证用户的邮箱等。",
"InterRouter": router.inter_router,
"ExposeRouter": router.public_router,
"Init": lambda: init(settings),
}


g_settings = None


def init(settings: Dynaconf):
print("Verify service is starting...")
global g_settings
g_settings = settings

24 changes: 24 additions & 0 deletions services/verify/db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from pony.orm import Database, Required, PrimaryKey

""" Create Database """
db = Database()


class OutsideVerifyCode(db.Entity):
code = PrimaryKey(str)
session = Required(str)
expired = Required(int)
callbackURI = Required(str)


class InsideVerifyCode(db.Entity):
code = PrimaryKey(str)
session = Required(str)
expired = Required(int)


db.bind(provider="sqlite", filename="verify.db")

db.generate_mapping(create_tables=True)

from pony.orm import db_session
160 changes: 160 additions & 0 deletions services/verify/router.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
"""
[service] Verify Service

* this: 本服务
* s1: 调用本服务的服务
* client: 用户的客户端

1. [s1] 请求内网api "/newVerify" 来进行一个新的验证 (需提供一个回调地址、一个 session ID)
2. [client] 通过路由请求内部api "/verifyOutsideCode" 进行验证
3. [this] 将 [client] 重定向到 "<CALLBACK> ?s= <SUCCESS> &v= <INSIDE-CODE>" (`SUCCESS` 为 `0/1`, 代表验证失败/成功, `INSIDE-CODE` 为内部验证码)
4. [s1] 请求内网api "/verifyInsideCode" 验证 `INSIDE-CODE`
5. [s1] 根据返回字段 `ok` 判断验证是否成功, `sess` 来恢复会话

"""

import fastapi
from fastapi import Request, Response
from starlette.responses import RedirectResponse

import verify
import send


inter_router = None
public_router = None


def init(ri: fastapi.APIRouter, rp: fastapi.APIRouter):
global inter_router
global public_router
inter_router = ri
public_router = rp

inter_router.add_route("/newVerifyCode", newVerifyCode, methods=["GET"])
inter_router.add_route("/verifyOutsideCode", verifyOutsideCode, methods=["GET"])
inter_router.add_route("/verifyInsideCode", verifyInsideCode, methods=["GET"])

public_router.add_route("/verify", verifyOutsideCode, methods=["GET"])


def _getVerifyUri(code: str):
"""
[Tool] 从验证码生成验证链接
"""
return f"https://openteens.org/verify/verify?code={code}"

def newVerify():
"""
[内部] 进行一个新的验证

Request:
method: str (one of [email])
target: str (e.g. "test@openteens.org")
session: str
callbackURI: str (建议使用带https的绝对路径)

Response:
..codeblock:: json
{
code: int
}
"""
request = Request()

method = request.args.get("method")
target = request.args.get("target")
session = request.args.get("session")
callbackURI = request.args.get("callbackURI")

code = verify.genOutsideCode(session, callbackURI)

if method == "email":
send.sendEmail(target, _getVerifyUri(code))
else:
return {"code": -1}

return {"code": 0}


def newVerifyCode():
"""
[内部] 进行一个新的验证(返回验证链接)

Request:
session: str
callbackURI: str (建议使用带https的绝对路径)

Response:
..codeblock:: json
{
code: int,
verifyUri: str
}
"""
request = Request()

session = request.args.get("session")
callbackURI = request.args.get("callbackURI")

code = verify.genOutsideCode(session, callbackURI)

return {"code": 0, "verifyUri": _getVerifyUri(code)}


def verifyOutsideCode():
"""
[外部] 验证外部验证码

Request:
code: str (外部验证码)

Response:
<Redirect> (重定向到回调地址)
"""
request = Request()

code = request.args.get("code")

result = verify.verifyOutsideCode(code)
if result:
sess = result["session"]
callbackURI = result["callbackURI"]

insideCode = verify.genInsideCode(sess)
redirectURI = f"{callbackURI}?s=1&v={insideCode}"
else:
redirectURI = "ERROR: Invalid Verification Link"

return RedirectResponse(redirectURI)


def verifyInsideCode():
"""
[内部] 验证内部验证码

Request:
code: str (内部验证码)

Response:
..codeblock:: json
{
code: int,
ok: bool,
sess: str
}
"""
request = Request()

code = request.args.get("code")

result = verify.verifyInsideCode(code)
if result:
return {"code": 0, "ok": True, "sess": result["session"]}
else:
return {"code": -1}


if __name__ == "__main__":
init(fastapi.APIRouter())
# router.run("localhost", 5003)
Loading