From 004ad4625169cad2325357aa174e789919ccb128 Mon Sep 17 00:00:00 2001
From: Paul Bienkowski
Date: Tue, 30 Nov 2021 23:32:42 +0100
Subject: [PATCH] Fix saving profile and add generating new API key
---
api/obs/api/routes/users.py | 19 +++++++----
frontend/src/pages/SettingsPage.tsx | 52 +++++++++++++++++++++++------
2 files changed, 55 insertions(+), 16 deletions(-)
diff --git a/api/obs/api/routes/users.py b/api/obs/api/routes/users.py
index 8fd3784..715c213 100644
--- a/api/obs/api/routes/users.py
+++ b/api/obs/api/routes/users.py
@@ -1,6 +1,9 @@
import logging
+import os
+import binascii
from sanic.response import json
+from sanic.exceptions import InvalidUsage
from obs.api.app import api, require_auth
@@ -16,7 +19,7 @@ def user_to_json(user):
"bio": user.bio,
"image": user.image,
"areTracksVisibleForAll": user.are_tracks_visible_for_all,
- # "apiKey": user.api_key,
+ "apiKey": user.api_key,
}
@@ -29,13 +32,17 @@ async def get_user(req):
@require_auth
async def put_user(req):
user = req.ctx.user
+ data = req.json
- for key in ["username", "email", "bio", "image"]:
- if key in req.json and isinstance(req.json[key], (str, type(None))):
- setattr(user, key, req.json[key])
+ for key in ["email", "bio", "image"]:
+ if key in data and isinstance(data[key], (str, type(None))):
+ setattr(user, key, data[key])
- if "areTracksVisibleForAll" in req.json:
- user.are_tracks_visible_for_all = bool(req.json["areTracksVisibleForAll"])
+ if "areTracksVisibleForAll" in data:
+ user.are_tracks_visible_for_all = bool(data["areTracksVisibleForAll"])
+
+ if data.get("updateApiKey"):
+ user.api_key = binascii.b2a_hex(os.urandom(16)).decode("ascii")
await req.ctx.db.commit()
return json(user_to_json(req.ctx.user))
diff --git a/frontend/src/pages/SettingsPage.tsx b/frontend/src/pages/SettingsPage.tsx
index daf3116..bcad107 100644
--- a/frontend/src/pages/SettingsPage.tsx
+++ b/frontend/src/pages/SettingsPage.tsx
@@ -19,8 +19,8 @@ const SettingsPage = connect((state) => ({login: state.login}), {setLogin})(func
setLoading(true)
setErrors(null)
try {
- const response = await api.put('/user', {body: {user: changes}})
- setLogin(response.user)
+ const response = await api.put('/user', {body: changes})
+ setLogin(response)
} catch (err) {
setErrors(err.errors)
} finally {
@@ -30,6 +30,19 @@ const SettingsPage = connect((state) => ({login: state.login}), {setLogin})(func
[setLoading, setLogin, setErrors]
)
+ const onGenerateNewKey = React.useCallback(async () => {
+ setLoading(true)
+ setErrors(null)
+ try {
+ const response = await api.put('/user', {body: {updateApiKey: true}})
+ setLogin(response)
+ } catch (err) {
+ setErrors(err.errors)
+ } finally {
+ setLoading(false)
+ }
+ }, [setLoading, setLogin, setErrors])
+
return (
@@ -41,7 +54,7 @@ const SettingsPage = connect((state) => ({login: state.login}), {setLogin})(func
@@ -62,7 +75,7 @@ const SettingsPage = connect((state) => ({login: state.login}), {setLogin})(func
-
+
@@ -101,7 +114,7 @@ function CopyInput({value, ...props}) {
const selectField = findInput((ref) => ref?.select())
-function ApiKeyDialog({login}) {
+function ApiKeyDialog({login, onGenerateNewKey}) {
const config = useConfig()
const [show, setShow] = React.useState(false)
const onClick = React.useCallback(
@@ -112,6 +125,14 @@ function ApiKeyDialog({login}) {
[setShow]
)
+ const onGenerateNewKeyInner = React.useCallback(
+ (e) => {
+ e.preventDefault()
+ onGenerateNewKey()
+ },
+ [onGenerateNewKey]
+ )
+
return (
<>
@@ -120,11 +141,15 @@ function ApiKeyDialog({login}) {
configuration interface to allow direct upload from the device.
Please protect your API Key carefully as it allows full control over your account.
-
+
{show ? (
- [
-
- ]
+ login.apiKey ? (
+ [
+
+ ]
+ ) : (
+
+ )
) : (
The API URL should be set to:
-
+
+
+
+
+ You can generate a new API Key here, which will invalidate the old one, disconnecting all devices you used it on
+ from your account.
+
+
>
)
}