removed v2/v1 division, working on user account system and file uploads

dev
Anton Franzluebbers 2022-09-05 02:33:05 -04:00
parent 1cb14d82df
commit 11260d9372
16 changed files with 279 additions and 465 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ env_win/
velconnect.db velconnect.db
velconnect*.db velconnect*.db
.idea/ .idea/
velconnect/data/

View File

@ -19,6 +19,28 @@ CREATE TABLE `UserCount` (
`platform` VARCHAR(64), `platform` VARCHAR(64),
PRIMARY KEY (`timestamp`, `hw_id`) PRIMARY KEY (`timestamp`, `hw_id`)
); );
CREATE TABLE `User` (
-- TODO user is defined by uuid, to which an email can be added without having to migrate.
-- then the data that is coming from a user vs device is constant
-- the user's email
`email` TEXT NOT NULL PRIMARY KEY,
`username` TEXT,
-- the first time this device was seen
`date_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- the last time this device data was modified
`last_modified` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
-- JSON containing arbitrary data
`data` TEXT
);
CREATE TABLE `UserDevice` (
-- Unique identifier for the device
`hw_id` TEXT NOT NULL,
-- the user's email
`email` TEXT NOT NULL,
-- when this connection was created
`date_created` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`hw_id`, `email`)
);
CREATE TABLE `Device` ( CREATE TABLE `Device` (
-- Unique identifier for this device -- Unique identifier for this device
`hw_id` TEXT NOT NULL PRIMARY KEY, `hw_id` TEXT NOT NULL PRIMARY KEY,

View File

@ -1,3 +1,4 @@
# syntax=docker/dockerfile:1
FROM python:3.10 FROM python:3.10
WORKDIR /usr/src/velconnect WORKDIR /usr/src/velconnect
COPY ./requirements.txt /usr/src/requirements.txt COPY ./requirements.txt /usr/src/requirements.txt

View File

@ -4,9 +4,7 @@ from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from routes.api import router as api_router from routes.api import router as api_router
from routes.api_v2 import router as api_v2_router
from routes.user_count import router as user_count_router from routes.user_count import router as user_count_router
from routes.user_count_v2 import router as user_count_v2_router
from routes.oculus_api import router as oculus_api_router from routes.oculus_api import router as oculus_api_router
from routes.website import router as website_router from routes.website import router as website_router
@ -17,6 +15,8 @@ origins = [
"https://velconnect.ugavel.com", "https://velconnect.ugavel.com",
"http://localhost", "http://localhost",
"http://localhost:8080", "http://localhost:8080",
"http://localhost:8000",
"http://localhost:8005",
] ]
app.add_middleware( app.add_middleware(
@ -30,9 +30,7 @@ app.add_middleware(
app.mount("/static", StaticFiles(directory="static"), name="static") app.mount("/static", StaticFiles(directory="static"), name="static")
app.include_router(api_router) app.include_router(api_router)
app.include_router(api_v2_router)
app.include_router(user_count_router) app.include_router(user_count_router)
app.include_router(user_count_v2_router)
app.include_router(oculus_api_router) app.include_router(oculus_api_router)
app.include_router(website_router) app.include_router(website_router)

2
velconnect/rebuild.sh Normal file → Executable file
View File

@ -1,4 +1,4 @@
docker build -t velconnect . docker build --tag velconnect .
docker rm web docker rm web
docker run -p 8081:80 --name web velconnect docker run -p 8081:80 --name web velconnect

View File

@ -4,3 +4,5 @@ uvicorn
pymysql pymysql
pyppeteer pyppeteer
jinja2 jinja2
python-multipart
aiofiles

View File

@ -1,34 +1,23 @@
from fastapi import APIRouter import secrets
from fastapi import Depends, HTTPException, status import json
import string
import aiofiles
import fastapi
from fastapi.responses import HTMLResponse from fastapi.responses import HTMLResponse
from fastapi.security import OAuth2PasswordBearer from fastapi import FastAPI, File, UploadFile
from pydantic import BaseModel
import db import db
db = db.DB("velconnect.db") db = db.DB("velconnect.db")
# APIRouter creates path operations for user module # APIRouter creates path operations for user module
router = APIRouter( router = fastapi.APIRouter(
prefix="/api", prefix="/api",
tags=["API"], tags=["API"],
responses={404: {"description": "Not found"}}, responses={404: {"description": "Not found"}},
) )
oauth2_scheme = OAuth2PasswordBearer(
tokenUrl="token") # use token authentication
def api_key_auth(api_key: str = Depends(oauth2_scheme)):
return True
values = db.query(
"SELECT * FROM `APIKey` WHERE `key`=:key;", {'key': api_key})
if not (len(values) > 0 and values['auth_level'] < 0):
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Forbidden"
)
@router.get("/", response_class=HTMLResponse, include_in_schema=False) @router.get("/", response_class=HTMLResponse, include_in_schema=False)
async def read_root(): async def read_root():
@ -36,7 +25,7 @@ async def read_root():
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<meta charset="utf-8"> <!-- Important: rapi-doc uses utf8 charecters --> <meta charset="utf-8">
<script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script> <script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
<title>API Reference</title> <title>API Reference</title>
</head> </head>
@ -58,138 +47,204 @@ async def read_root():
""" """
@router.get('/get_all_headsets') def parse_device(device: dict):
def get_all_headsets(): if 'data' in device and device['data'] is not None and len(device['data']) > 0:
"""Returns a list of all headsets and details associated with them.""" device['data'] = json.loads(device['data'])
values = db.query("SELECT * FROM `Headset`;")
@router.get('/get_all_devices')
def get_all_devices():
"""Returns a list of all devices and details associated with them."""
values = db.query("SELECT * FROM `Device`;")
values = [dict(v) for v in values]
for device in values:
parse_device(device)
return values return values
@router.get('/pair_headset/{pairing_code}') @router.get('/get_device_by_pairing_code/{pairing_code}')
def pair_headset(pairing_code: str): def get_device_by_pairing_code(pairing_code: str):
values = db.query("SELECT * FROM `Headset` WHERE `pairing_code`=:pairing_code;", values = db.query("SELECT * FROM `Device` WHERE `pairing_code`=:pairing_code;",
{'pairing_code': pairing_code}) {'pairing_code': pairing_code})
if len(values) == 1: if len(values) == 1:
return values[0] device = dict(values[0])
parse_device(device)
return device
return {'error': 'Not found'}, 400 return {'error': 'Not found'}, 400
class UpdatePairingCode(BaseModel): def create_device(hw_id: str):
hw_id: str
pairing_code: int
@router.post('/update_pairing_code')
def update_pairing_code(data: UpdatePairingCode):
"""This also creates a headset if it doesn't exist"""
print("Update pairing code")
print(data)
create_headset(data.hw_id)
db.insert(""" db.insert("""
UPDATE `Headset` INSERT OR IGNORE INTO `Device`(hw_id) VALUES (:hw_id);
SET `pairing_code`=:pairing_code, `last_used`=CURRENT_TIMESTAMP
WHERE `hw_id`=:hw_id;
""", data.dict())
return {'success': True}
def create_headset(hw_id: str):
db.insert("""
db.insert IGNORE INTO Headset(hw_id) VALUES (:hw_id);
""", {'hw_id': hw_id}) """, {'hw_id': hw_id})
@router.get('/get_state/{hw_id}') @router.get('/device/get_data/{hw_id}')
def get_headset_details(hw_id: str): def get_state(request: fastapi.Request, hw_id: str):
data = get_headset_details_db(hw_id) """Gets the device state"""
if data is None:
return {'error': "Can't find headset with that id."}
else:
return data
devices = db.query("""
def get_headset_details_db(hw_id): SELECT * FROM `Device` WHERE `hw_id`=:hw_id;
headsets = db.query("""
SELECT * FROM `Headset` WHERE `hw_id`=:hw_id;
""", {'hw_id': hw_id}) """, {'hw_id': hw_id})
if len(headsets) == 0: if len(devices) == 0:
return None return {'error': "Can't find device with that id."}
block = dict(devices[0])
if 'data' in block and block['data'] is not None:
block['data'] = json.loads(block['data'])
room = get_room_details_db(headsets[0]['current_room']) room_key: str = f"{devices[0]['current_app']}_{devices[0]['current_room']}"
room_data = get_data(room_key)
return {'user': headsets[0], 'room': room} if "error" in room_data:
set_data(request, data={}, key=room_key, modified_by=None, category="room")
room_data = get_data(room_key)
return {'device': block, 'room': room_data}
@router.post('/set_headset_details/{hw_id}') @router.post('/device/set_data/{hw_id}')
def set_headset_details_generic(hw_id: str, data: dict): def set_state(request: fastapi.Request, hw_id: str, data: dict, modified_by: str = None):
print("Data:") """Sets the device state"""
print(data)
# create_headset(hw_id) create_device(hw_id)
allowed_keys = [ # add the client's IP address if no sender specified
if 'modified_by' in data:
modified_by = data['modified_by']
if modified_by is None:
modified_by: str = str(request.client) + "_" + str(request.headers)
allowed_keys: list[str] = [
'os_info',
'friendly_name',
'current_app',
'current_room', 'current_room',
'pairing_code', 'pairing_code',
'user_color',
'user_name',
'avatar_url',
'user_details',
'streamer_stream_id',
'streamer_control_id',
]
for key in data:
if key in allowed_keys:
if key == 'current_room':
create_room(data['current_room'])
db.insert(f"UPDATE `Headset` SET {key}=:value, modified_by=:sender_id WHERE `hw_id`=:hw_id;", {
'value': data[key], 'hw_id': hw_id, 'sender_id': data['sender_id']})
return {'success': True}
@router.post('/set_room_details/{room_id}')
def set_room_details_generic(room_id: str, data: dict):
print(data)
allowed_keys = [
'modified_by',
'whitelist',
'tv_url',
'carpet_color',
'room_details',
] ]
for key in data: for key in data:
if key in allowed_keys: if key in allowed_keys:
db.insert("UPDATE `Room` SET " + key + db.insert(f"""
"=:value, modified_by=:sender_id WHERE `room_id`=:room_id;", UPDATE `Device`
{'value': data[key], 'room_id': room_id, 'sender_id': data['sender_id']}) SET {key}=:value,
last_modified=CURRENT_TIMESTAMP,
modified_by=:modified_by
WHERE `hw_id`=:hw_id;
""",
{
'value': data[key],
'hw_id': hw_id,
'modified_by': modified_by
})
if key == "data":
new_data = data['data']
# get the old json values and merge the data
old_data_query = db.query("""
SELECT data
FROM `Device`
WHERE hw_id=:hw_id
""", {"hw_id": hw_id})
if len(old_data_query) == 1:
old_data: dict = {}
if old_data_query[0]['data'] is not None:
old_data = json.loads(old_data_query[0]["data"])
new_data = {**old_data, **new_data}
# add the data to the db
db.insert("""
UPDATE `Device`
SET data=:data,
last_modified=CURRENT_TIMESTAMP
WHERE hw_id=:hw_id;
""", {"hw_id": hw_id, "data": json.dumps(new_data)})
return {'success': True} return {'success': True}
@router.get('/get_room_details/{room_id}') def generate_id(length: int = 4) -> str:
def get_room_details(room_id: str): return ''.join(
return get_room_details_db(room_id) secrets.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for i in range(length))
def get_room_details_db(room_id): @router.post('/set_data')
values = db.query(""" def set_data_with_random_key(request: fastapi.Request, data: dict, modified_by: str = None,
SELECT * FROM `Room` WHERE room_id=:room_id; category: str = None) -> dict:
""", {'room_id': room_id}) """Creates a little storage bucket for arbitrary data with a random key"""
if len(values) == 1: return set_data(request, data, None, modified_by, category)
return values[0]
else:
return None
def create_room(room_id): @router.post('/set_data/{key}')
def set_data(request: fastapi.Request, data: dict, key: str = None, modified_by: str = None,
category: str = None) -> dict:
"""Creates a little storage bucket for arbitrary data"""
# add the client's IP address if no sender specified
if 'modified_by' in data:
modified_by = data['modified_by']
if modified_by is None:
modified_by: str = str(request.client) + "_" + str(request.headers)
# generates a key if none was supplied
if key is None:
key = generate_id()
# regenerate if necessary
while len(db.query("SELECT id FROM `DataBlock` WHERE id=:id;", {"id": key})) > 0:
key = generate_id()
# get the old json values and merge the data
old_data_query = db.query("""
SELECT data
FROM `DataBlock`
WHERE id=:id
""", {"id": key})
if len(old_data_query) == 1:
old_data: dict = json.loads(old_data_query[0]["data"])
data = {**old_data, **data}
# add the data to the db
db.insert(""" db.insert("""
db.insert IGNORE INTO `Room`(room_id) REPLACE INTO `DataBlock` (id, category, modified_by, data, last_modified)
VALUES( VALUES(:id, :category, :modified_by, :data, CURRENT_TIMESTAMP);
:room_id """, {"id": key, "category": category, "modified_by": modified_by, "data": json.dumps(data)})
);
""", {'room_id': room_id})
return {'room_id': room_id}
return {'key': key}
@router.get('/get_data/{key}')
def get_data(key: str) -> dict:
"""Gets data from a storage bucket for arbitrary data"""
data = db.query("""
SELECT *
FROM `DataBlock`
WHERE id=:id
""", {"id": key})
db.insert("""
UPDATE `DataBlock`
SET last_accessed = CURRENT_TIMESTAMP
WHERE id=:id;
""", {"id": key})
try:
if len(data) == 1:
block = dict(data[0])
if 'data' in block and block['data'] is not None:
block['data'] = json.loads(block['data'])
return block
return {'error': 'Not found'}
except Exception as e:
print(e)
return {'error': 'Unknown. Maybe no data at this key.'}
@router.post("/upload_file/{key}")
async def upload_file(request: fastapi.Request, file: UploadFile, key: str,modified_by: str = None):
async with aiofiles.open('data/' + key, 'wb') as out_file:
content = await file.read() # async read
await out_file.write(content) # async write
# add a datablock to link to the file
set_data(request, {'filename': file.filename}, key, 'file')
return {"filename": file.filename}

View File

@ -1,232 +0,0 @@
import secrets
import json
import string
import fastapi
from fastapi.responses import HTMLResponse
import db
db = db.DB("velconnect_v2.db")
# APIRouter creates path operations for user module
router = fastapi.APIRouter(
prefix="/api/v2",
tags=["API V2"],
responses={404: {"description": "Not found"}},
)
@router.get("/", response_class=HTMLResponse, include_in_schema=False)
async def read_root():
return """
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script type="module" src="https://unpkg.com/rapidoc/dist/rapidoc-min.js"></script>
<title>API Reference</title>
</head>
<body>
<rapi-doc
render-style = "read"
primary-color = "#bc1f2d"
show-header = "false"
show-info = "true"
spec-url = "/openapi.json"
default-schema-tab = 'example'
>
<div slot="nav-logo" style="display: flex; align-items: center; justify-content: center;">
<img src = "/static/img/velconnect_logo_1.png" style="width:10em; margin: 2em auto;" />
</div>
</rapi-doc>
</body>
</html>
"""
@router.get('/get_all_devices')
def get_all_devices():
"""Returns a list of all devices and details associated with them."""
values = db.query("SELECT * FROM `Device`;")
values = [dict(v) for v in values]
for device in values:
if 'data' in device and len(device['data']) > 0:
device['data'] = json.loads(device['data'])
return values
@router.get('/get_device_by_pairing_code/{pairing_code}')
def get_device_by_pairing_code(pairing_code: str):
values = db.query("SELECT * FROM `Device` WHERE `pairing_code`=:pairing_code;",
{'pairing_code': pairing_code})
if len(values) == 1:
return values[0]
return {'error': 'Not found'}, 400
def create_device(hw_id: str):
db.insert("""
INSERT OR IGNORE INTO `Device`(hw_id) VALUES (:hw_id);
""", {'hw_id': hw_id})
@router.get('/device/get_data/{hw_id}')
def get_state(request: fastapi.Request, hw_id: str):
"""Gets the device state"""
devices = db.query("""
SELECT * FROM `Device` WHERE `hw_id`=:hw_id;
""", {'hw_id': hw_id})
if len(devices) == 0:
return {'error': "Can't find device with that id."}
block = dict(devices[0])
if 'data' in block and block['data'] is not None:
block['data'] = json.loads(block['data'])
room_key: str = f"{devices[0]['current_app']}_{devices[0]['current_room']}"
room_data = get_data(room_key)
if "error" in room_data:
set_data(request, data={}, key=room_key, modified_by=None, category="room")
room_data = get_data(room_key)
return {'device': block, 'room': room_data}
@router.post('/device/set_data/{hw_id}')
def set_state(request: fastapi.Request, hw_id: str, data: dict, modified_by: str = None):
"""Sets the device state"""
create_device(hw_id)
# add the client's IP address if no sender specified
if 'modified_by' in data:
modified_by = data['modified_by']
if modified_by is None:
modified_by: str = str(request.client) + "_" + str(request.headers)
allowed_keys: list[str] = [
'os_info',
'friendly_name',
'current_app',
'current_room',
'pairing_code',
]
for key in data:
if key in allowed_keys:
db.insert(f"""
UPDATE `Device`
SET {key}=:value,
last_modified=CURRENT_TIMESTAMP,
modified_by=:modified_by
WHERE `hw_id`=:hw_id;
""",
{
'value': data[key],
'hw_id': hw_id,
'modified_by': modified_by
})
if key == "data":
new_data = data['data']
# get the old json values and merge the data
old_data_query = db.query("""
SELECT data
FROM `Device`
WHERE hw_id=:hw_id
""", {"hw_id": hw_id})
if len(old_data_query) == 1:
old_data: dict = {}
if old_data_query[0]['data'] is not None:
old_data = json.loads(old_data_query[0]["data"])
new_data = {**old_data, **new_data}
# add the data to the db
db.insert("""
UPDATE `Device`
SET data=:data,
last_modified=CURRENT_TIMESTAMP
WHERE hw_id=:hw_id;
""", {"hw_id": hw_id, "data": json.dumps(new_data)})
return {'success': True}
def generate_id(length: int = 4) -> str:
return ''.join(
secrets.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for i in range(length))
@router.post('/set_data')
def set_data_with_random_key(request: fastapi.Request, data: dict, modified_by: str = None,
category: str = None) -> dict:
"""Creates a little storage bucket for arbitrary data with a random key"""
return set_data(request, data, None, modified_by, category)
@router.post('/set_data/{key}')
def set_data(request: fastapi.Request, data: dict, key: str = None, modified_by: str = None,
category: str = None) -> dict:
"""Creates a little storage bucket for arbitrary data"""
# add the client's IP address if no sender specified
if 'modified_by' in data:
modified_by = data['modified_by']
if modified_by is None:
modified_by: str = str(request.client) + "_" + str(request.headers)
# generates a key if none was supplied
if key is None:
key = generate_id()
# regenerate if necessary
while len(db.query("SELECT id FROM `DataBlock` WHERE id=:id;", {"id": key})) > 0:
key = generate_id()
# get the old json values and merge the data
old_data_query = db.query("""
SELECT data
FROM `DataBlock`
WHERE id=:id
""", {"id": key})
if len(old_data_query) == 1:
old_data: dict = json.loads(old_data_query[0]["data"])
data = {**old_data, **data}
# add the data to the db
db.insert("""
REPLACE INTO `DataBlock` (id, category, modified_by, data, last_modified)
VALUES(:id, :category, :modified_by, :data, CURRENT_TIMESTAMP);
""", {"id": key, "category": category, "modified_by": modified_by, "data": json.dumps(data)})
return {'key': key}
@router.get('/get_data/{key}')
def get_data(key: str) -> dict:
"""Gets data from a storage bucket for arbitrary data"""
data = db.query("""
SELECT *
FROM `DataBlock`
WHERE id=:id
""", {"id": key})
db.insert("""
UPDATE `DataBlock`
SET last_accessed = CURRENT_TIMESTAMP
WHERE id=:id;
""", {"id": key})
try:
if len(data) == 1:
block = dict(data[0])
if 'data' in block and block['data'] is not None:
block['data'] = json.loads(block['data'])
return block
return {'error': 'Not found'}
except Exception as e:
print(e)
return {'error': 'Unknown. Maybe no data at this key.'}

View File

@ -28,27 +28,41 @@ post_user_count_example = {
@router.post('/update_user_count') @router.post('/update_user_count')
def update_user_count(data: dict): def update_user_count(data: dict = fastapi.Body(..., examples=post_user_count_example)) -> dict:
if 'app_id' not in data:
data['app_id'] = ""
db.insert(""" db.insert("""
REPLACE INTO `UserCount` REPLACE INTO `UserCount` (
timestamp,
hw_id,
app_id,
room_id,
total_users,
room_users,
version,
platform
)
VALUES( VALUES(
CURRENT_TIMESTAMP, CURRENT_TIMESTAMP,
%(hw_id)s, :hw_id,
%(room_id)s, :app_id,
%(total_users)s, :room_id,
%(room_users)s, :total_users,
%(version)s, :room_users,
%(platform)s :version,
:platform
); );
""", data) """, data)
return {'success': True} return {'success': True}
@router.get('/get_user_count') @router.get('/get_user_count')
def get_user_count(hours: float = 24): def get_user_count(app_id: str = None, hours: float = 24) -> list:
values = db.query(""" values = db.query("""
SELECT timestamp, total_users SELECT timestamp, total_users
FROM `UserCount` FROM `UserCount`
WHERE TIMESTAMP > DATE_SUB(NOW(), INTERVAL """ + str(hours) + """ HOUR); WHERE app_id = :app_id AND
""") timestamp > datetime('now', '-""" + str(hours) + """ Hour');
""", {"app_id": app_id})
return values return values

View File

@ -1,68 +0,0 @@
import fastapi
import db
db = db.DB("velconnect_v2.db")
# APIRouter creates path operations for user module
router = fastapi.APIRouter(
prefix="/api/v2",
tags=["User Count V2"],
responses={404: {"description": "Not found"}},
)
post_user_count_example = {
"default": {
"summary": "Example insert for user count",
"value": {
"hw_id": "1234",
"app_id": "example",
"room_id": "0",
"total_users": 1,
"room_users": 1,
"version": "0.1",
"platform": "Windows"
}
}
}
@router.post('/update_user_count')
def update_user_count(data: dict = fastapi.Body(..., examples=post_user_count_example)) -> dict:
if 'app_id' not in data:
data['app_id'] = ""
db.insert("""
REPLACE INTO `UserCount` (
timestamp,
hw_id,
app_id,
room_id,
total_users,
room_users,
version,
platform
)
VALUES(
CURRENT_TIMESTAMP,
:hw_id,
:app_id,
:room_id,
:total_users,
:room_users,
:version,
:platform
);
""", data)
return {'success': True}
@router.get('/get_user_count')
def get_user_count(app_id: str = None, hours: float = 24) -> list:
values = db.query("""
SELECT timestamp, total_users
FROM `UserCount`
WHERE app_id = :app_id AND
timestamp > datetime('now', '-""" + str(hours) + """ Hour');
""", {"app_id": app_id})
return values

View File

@ -29,8 +29,8 @@ def success():
@router.get('/failure') @router.get('/failure')
def failure(): def failure(request: fastapi.Request, code: int = 0):
return FileResponse("templates/failure.html") return templates.TemplateResponse("failure.html", {"request": request, "code": code})
@router.get('/join/{app_id}/{link}') @router.get('/join/{app_id}/{link}')

View File

@ -4,7 +4,7 @@
if (hw_id !== "" && hw_id !== undefined && hw_id !== "undefined") { if (hw_id !== "" && hw_id !== undefined && hw_id !== "undefined") {
httpGetAsync('/api/v2/device/get_data/' + hw_id, (resp) => { httpGetAsync('/api/device/get_data/' + hw_id, (resp) => {
console.log(resp); console.log(resp);
let respData = JSON.parse(resp); let respData = JSON.parse(resp);

View File

@ -1,6 +1,6 @@
function setDeviceField(device) { function setDeviceField(device) {
let hw_id = getCookie('hw_id'); let hw_id = getCookie('hw_id');
fetch('/api/v2/device/set_data/' + hw_id, { fetch('/api/device/set_data/' + hw_id, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
@ -15,7 +15,7 @@ function setDeviceField(device) {
function setDeviceData(data, successCallback, failureCallback) { function setDeviceData(data, successCallback, failureCallback) {
let hw_id = getCookie('hw_id'); let hw_id = getCookie('hw_id');
fetch('/api/v2/device/set_data/' + hw_id, { fetch('/api/device/set_data/' + hw_id, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
@ -35,7 +35,7 @@ function setDeviceData(data, successCallback, failureCallback) {
} }
function setRoomData(data) { function setRoomData(data) {
fetch('/api/v2/set_data/' + current_app.value + "_" + current_room.value, { fetch('/api/set_data/' + current_app.value + "_" + current_room.value, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',

View File

@ -1,7 +1,9 @@
<html> <!DOCTYPE html>
<html lang="en">
<head> <head>
<title>Failure</title>
<link rel="apple-touch-icon" sizes="180x180" href="/static/favicons/apple-touch-icon.png"> <link rel="apple-touch-icon" sizes="180x180" href="/static/favicons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicons/favicon-32x32.png"> <link rel="icon" type="image/png" sizes="32x32" href="/static/favicons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicons/favicon-16x16.png"> <link rel="icon" type="image/png" sizes="16x16" href="/static/favicons/favicon-16x16.png">
@ -27,9 +29,17 @@
</head> </head>
<body> <body>
<div class="centered"> <div class="centered">
🤮 FAIL 🤡 🤮 FAIL 🤡
</div> </div>
<div class="centered">
{% if code==1 %}
<p>Pairing code not recognized. Go back and try again.</p>
{% else %}
<p>Unknown error</p>
{% endif %}
</div>
</body> </body>
</html> </html>

View File

@ -259,7 +259,7 @@
if (hw_id !== "" && hw_id !== undefined && hw_id !== "undefined") { if (hw_id !== "" && hw_id !== undefined && hw_id !== "undefined") {
httpGetAsync('/api/v2/device/get_data/' + hw_id, (resp) => { httpGetAsync('/api/device/get_data/' + hw_id, (resp) => {
console.log(resp); console.log(resp);
let respData = JSON.parse(resp); let respData = JSON.parse(resp);
@ -309,7 +309,7 @@
function setDeviceField(data) { function setDeviceField(data) {
fetch('/api/v2/device/set_data/' + hw_id, { fetch('/api/device/set_data/' + hw_id, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
@ -323,7 +323,7 @@
} }
function setDeviceData(data) { function setDeviceData(data) {
fetch('/api/v2/device/set_data/' + hw_id, { fetch('/api/device/set_data/' + hw_id, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
@ -337,7 +337,7 @@
} }
function setRoomData(data) { function setRoomData(data) {
fetch('/api/v2/set_data/' + current_app.value + "_" + current_room.value, { fetch('/api/set_data/' + current_app.value + "_" + current_room.value, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',

View File

@ -1,3 +1,4 @@
<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -69,7 +70,7 @@
You can find the code in the bottom left of your menu tablet in conVRged. You can find the code in the bottom left of your menu tablet in conVRged.
</div> </div>
<div class="card-footer centered"> <div class="card-footer centered">
<form onsubmit="submitCode()"> <form id="pair_form">
<label for="pair_code"></label><input class="btn" type="text" id="pair_code" placeholder="0000"> <label for="pair_code"></label><input class="btn" type="text" id="pair_code" placeholder="0000">
<input class="btn btn-primary" id="submit_pairing_code" type="submit" value="Submit"/> <input class="btn btn-primary" id="submit_pairing_code" type="submit" value="Submit"/>
</form> </form>
@ -81,18 +82,28 @@
const pair_code_input = document.getElementById('pair_code'); const pair_code_input = document.getElementById('pair_code');
function submitCode() { document.getElementById('pair_form').addEventListener('submit', submitCode, true);
fetch('/api/v2/get_device_by_pairing_code/' + pair_code_input.value).then(resp => resp.json()).then(resp => {
console.log(resp); function submitCode(event) {
let respData = JSON.parse(resp); fetch('/api/get_device_by_pairing_code/' + pair_code_input.value)
if (respData['hw_id'] !== '') { .then(resp => resp.json())
setCookie('hw_id', respData['hw_id'], 60); .then(resp => {
window.location.href = "/"; if (resp.length === 2 && resp[1] === 400) {
} window.location.href = "/failure?code=1";
}).catch(e => { console.error(resp);
} else {
let respData = JSON.parse(resp);
if (respData['hw_id'] !== '') {
setCookie('hw_id', respData['hw_id'], 60);
window.location.href = "/";
}
}
}).catch(e => {
window.location.href = "/failure"; window.location.href = "/failure";
console.error(e); console.error(e);
}); });
event.preventDefault();
return false;
} }
</script> </script>
</body> </body>