134 lines
4.2 KiB
Python
134 lines
4.2 KiB
Python
import sys
|
|
import json
|
|
import asyncio
|
|
|
|
from database import create_sql_engine, User, Agent
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy.sql.expression import select
|
|
from quart import Quart, Response, request, send_from_directory, jsonify, websocket
|
|
|
|
class App:
|
|
def __init__(self, data_directory):
|
|
self.data_directory = data_directory
|
|
self.sql_engine = create_sql_engine(self.data_directory)
|
|
|
|
def sql_session(self):
|
|
return Session(self.sql_engine)
|
|
|
|
app = App("./")
|
|
|
|
def start_server(app):
|
|
server = Quart(__name__, static_folder='../frontend/build/web')
|
|
|
|
@server.route('/')
|
|
async def index():
|
|
return await send_from_directory(server.static_folder, 'index.html')
|
|
|
|
@server.route('/<path:path>')
|
|
async def serve_static(path):
|
|
return await send_from_directory(server.static_folder, path)
|
|
|
|
@server.route('/user/signup', methods=['POST'])
|
|
async def signup():
|
|
data = await request.get_json()
|
|
|
|
user_id = None
|
|
|
|
username = data['username']
|
|
email = data['email']
|
|
password = data['password']
|
|
|
|
with app.sql_session() as session:
|
|
result = session.execute(
|
|
select(User.id).where(User.email == email or User.username == username)
|
|
).first()
|
|
|
|
if result is None:
|
|
user = User()
|
|
user.email = email
|
|
user.username = username
|
|
user.password = password
|
|
|
|
session.add(user)
|
|
session.commit()
|
|
|
|
user_id = user.id
|
|
print(f"Created user #{user_id}: {username} ({email})")
|
|
else:
|
|
user_id = None
|
|
print(f"Signup error: '{email}' or '{username}' are already used")
|
|
|
|
if user_id is None:
|
|
return {"error": "existing credentials"}
|
|
else:
|
|
# token = auth_manager.dump_token(user_id)
|
|
return {"userId": user_id}
|
|
|
|
@server.websocket('/ws')
|
|
async def ws():
|
|
print("incoming ws")
|
|
|
|
# Authenticate before dedicating any resources
|
|
auth_req = json.loads(await websocket.receive())
|
|
if "username" not in auth_req:
|
|
print("Invalid auth request:", auth_req)
|
|
await websocket.send(json.dumps({'error': 'invalid auth'}))
|
|
return
|
|
|
|
# TODO: Actually authenticate credentials against stored users
|
|
# TODO: Get the user id from the credentials, use them in create-agent
|
|
print(f"User {auth_req['username']} connected")
|
|
|
|
send_queue = asyncio.Queue()
|
|
|
|
async def sender_task():
|
|
nonlocal send_queue
|
|
while True:
|
|
msg = await send_queue.get()
|
|
await websocket.send(json.dumps(msg))
|
|
|
|
async def send(msg):
|
|
await send_queue.put(msg)
|
|
|
|
asyncio.create_task(sender_task())
|
|
|
|
while True:
|
|
req = json.loads(await websocket.receive())
|
|
|
|
action = req['action']
|
|
body = req.get('body', {})
|
|
nonce = req.get('nonce', None)
|
|
|
|
if action == "ping":
|
|
print("ping")
|
|
await send({'content': "pong"})
|
|
elif action == "create-agent":
|
|
with app.sql_session() as session:
|
|
agent = Agent()
|
|
|
|
agent.user_id = None
|
|
agent.name = body['name']
|
|
agent.description = body['description']
|
|
agent.picture = body.get('picture')
|
|
agent.kind = body['kind']
|
|
agent.data = body['data']
|
|
|
|
session.add(agent)
|
|
session.commit()
|
|
|
|
print(f"Created user #{agent.id}: {agent.name}")
|
|
await send({'content': "agent created", 'agentId': agent.id, 'nonce': nonce})
|
|
else:
|
|
print("Unknown message: " + action)
|
|
|
|
server.run(debug=True)
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) > 1:
|
|
data_directory = sys.argv[1]
|
|
else:
|
|
print("No directory specified. Using current directory as default.")
|
|
data_directory = "."
|
|
|
|
app = App(data_directory)
|
|
start_server(app) |