feat: init ap server w webfinger endpoint
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
faa67e9408
commit
73430848e8
6 changed files with 120 additions and 0 deletions
0
ap/__init__.py
Normal file
0
ap/__init__.py
Normal file
12
ap/__main__.py
Normal file
12
ap/__main__.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
if __name__ == "__main__":
|
||||||
|
from .config import Config
|
||||||
|
from .db import Database
|
||||||
|
from .server import app
|
||||||
|
|
||||||
|
db = Database()
|
||||||
|
db.add_user("alice")
|
||||||
|
|
||||||
|
config = Config()
|
||||||
|
config.options["port"] = 9003
|
||||||
|
config.options["hostname"] = f'lab.batsense.net:{config.options["port"]}'
|
||||||
|
app.run(host="0.0.0.0", port=config.options["port"], debug=True)
|
12
ap/config.py
Normal file
12
ap/config.py
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
from ftest_common.logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
class Config(object):
|
||||||
|
_instance = None
|
||||||
|
options = {}
|
||||||
|
|
||||||
|
def __new__(cls):
|
||||||
|
if cls._instance is None:
|
||||||
|
logger.info("Creating the config")
|
||||||
|
cls._instance = super(Config, cls).__new__(cls)
|
||||||
|
return cls._instance
|
26
ap/db.py
Normal file
26
ap/db.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
from ftest_common.logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
class Database(object):
|
||||||
|
_instance = None
|
||||||
|
db = {}
|
||||||
|
# { "user": [{name: foo..}{..}{..}] }
|
||||||
|
|
||||||
|
def __new__(cls):
|
||||||
|
if cls._instance is None:
|
||||||
|
logger.info("Creating the store")
|
||||||
|
cls._instance = super(Database, cls).__new__(cls)
|
||||||
|
return cls._instance
|
||||||
|
|
||||||
|
def get_user(self, username):
|
||||||
|
for u in self.db["users"]:
|
||||||
|
print(u)
|
||||||
|
if u["username"] == username:
|
||||||
|
return u
|
||||||
|
return None
|
||||||
|
|
||||||
|
def add_user(self, username):
|
||||||
|
if "users" not in self.db:
|
||||||
|
self.db["users"] = []
|
||||||
|
|
||||||
|
self.db["users"].append({"username": username})
|
17
ap/errors.py
Normal file
17
ap/errors.py
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
from flask import jsonify, Response as FlaskResponse
|
||||||
|
|
||||||
|
|
||||||
|
def bad_req(msg):
|
||||||
|
"""400 bad request status code"""
|
||||||
|
res = FlaskResponse()
|
||||||
|
res.status_code = 400
|
||||||
|
res.data = msg
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def not_found(msg):
|
||||||
|
"""404 not found request status code"""
|
||||||
|
res = FlaskResponse()
|
||||||
|
res.status_code = 404
|
||||||
|
res.data = msg
|
||||||
|
return res
|
53
ap/server.py
Normal file
53
ap/server.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
from flask import Flask, request, jsonify
|
||||||
|
from flask_cors import CORS, cross_origin
|
||||||
|
|
||||||
|
from .config import Config
|
||||||
|
from .db import Database
|
||||||
|
from .errors import bad_req, not_found
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
JRD_JSON = "application/jrd+json; charset=utf-8"
|
||||||
|
|
||||||
|
WEBFINGER_ROUTE = "/.well-known/webfinger"
|
||||||
|
|
||||||
|
@app.route(WEBFINGER_ROUTE, methods=["GET"])
|
||||||
|
@cross_origin()
|
||||||
|
def hello_world():
|
||||||
|
config = Config()
|
||||||
|
db = Database()
|
||||||
|
|
||||||
|
resource = request.args.get("resource")
|
||||||
|
if resource is None:
|
||||||
|
bad_req("webfinger must have 'resource' arg")
|
||||||
|
if "acct:" not in resource:
|
||||||
|
return bad_req("webfinger resource query must have 'acct'")
|
||||||
|
if "@" not in resource:
|
||||||
|
return bad_req("webfinger resource query must have '@'")
|
||||||
|
|
||||||
|
parts = resource.split("acct:")
|
||||||
|
parts = parts[1].split("@")
|
||||||
|
username = parts[0]
|
||||||
|
hostname = parts[1]
|
||||||
|
if hostname != config.options["hostname"]:
|
||||||
|
bad_req(f"Only serves hostname {config.options['hostname']}")
|
||||||
|
user = db.get_user(username)
|
||||||
|
if user is None:
|
||||||
|
return not_found(f"resource {username} not found")
|
||||||
|
|
||||||
|
resp = jsonify(
|
||||||
|
{
|
||||||
|
"subject": f"acct:{username}@{hostname}",
|
||||||
|
"aliases": [f"http://{hostname}/@{username}"],
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"rel": "self",
|
||||||
|
"type": "application/activity+json",
|
||||||
|
"href": f"http://{hostname}/users/{username}",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
resp.headers["Content-Type"] = JRD_JSON
|
||||||
|
return resp
|
Loading…
Reference in a new issue