Updates to the admin to reflect new stream keys and admin password split

This commit is contained in:
Gabe Kangas 2022-11-28 20:22:26 -08:00
parent c4dc802941
commit d503c8a2e0
8 changed files with 205 additions and 17 deletions

View File

@ -173,6 +173,10 @@ export const MainLayout: FC<MainLayoutProps> = ({ children }) => {
label: <Link href="/admin/config-server-details">Server Setup</Link>,
key: 'config-server-details',
},
{
label: <Link href="/admin/config/streamkeys/">Server Setup</Link>,
key: 'config-streamkeys',
},
{
label: <Link href="/admin/config-video">Video</Link>,
key: 'config-video',

View File

@ -26,7 +26,7 @@ export const Offline: FC<OfflineProps> = ({ logs = [], config }) => {
const serverStatusData = useContext(ServerStatusContext);
const { serverConfig } = serverStatusData || {};
const { streamKey, rtmpServerPort } = serverConfig;
const { rtmpServerPort } = serverConfig;
const instanceUrl = global.window?.location.hostname || '';
let rtmpURL;
@ -58,11 +58,11 @@ export const Offline: FC<OfflineProps> = ({ logs = [], config }) => {
</Paragraph>
)}
<Text strong className="stream-info-label">
Stream Key:
Streaming Keys:
</Text>
<Text strong className="stream-info-box">
<Link href="/admin/config/streamkeys"> View </Link>
</Text>
<Paragraph className="stream-info-box" copyable={{ text: streamKey }}>
*********************
</Paragraph>
</div>
</div>
),

View File

@ -9,7 +9,7 @@ import {
TEXTFIELD_PROPS_FFMPEG,
TEXTFIELD_PROPS_RTMP_PORT,
TEXTFIELD_PROPS_SOCKET_HOST_OVERRIDE,
TEXTFIELD_PROPS_STREAM_KEY,
TEXTFIELD_PROPS_ADMIN_PASSWORD,
TEXTFIELD_PROPS_WEB_PORT,
} from '../../utils/config-constants';
import { UpdateArgs } from '../../types/config-section';
@ -24,7 +24,7 @@ export const EditInstanceDetails = () => {
const { serverConfig } = serverStatusData || {};
const { streamKey, ffmpegPath, rtmpServerPort, webServerPort, yp, socketHostOverride } =
const { adminPassword, ffmpegPath, rtmpServerPort, webServerPort, yp, socketHostOverride } =
serverConfig;
const [copyIsVisible, setCopyVisible] = useState(false);
@ -33,7 +33,7 @@ export const EditInstanceDetails = () => {
useEffect(() => {
setFormDataValues({
streamKey,
adminPassword,
ffmpegPath,
rtmpServerPort,
webServerPort,
@ -89,10 +89,10 @@ export const EditInstanceDetails = () => {
<div className="field-container field-streamkey-container">
<div className="left-side">
<TextFieldWithSubmit
fieldName="streamKey"
{...TEXTFIELD_PROPS_STREAM_KEY}
value={formDataValues.streamKey}
initialValue={streamKey}
fieldName="adminPassword"
{...TEXTFIELD_PROPS_ADMIN_PASSWORD}
value={formDataValues.adminPassword}
initialValue={adminPassword}
type={TEXTFIELD_TYPE_PASSWORD}
onChange={handleFieldChange}
onSubmit={showStreamKeyChangeMessage}

View File

@ -0,0 +1,174 @@
import React, { useContext, useState } from 'react';
import { Table, Space, Button, Typography, Alert, Input, Form } from 'antd';
import { DeleteOutlined, EyeOutlined, PlusOutlined } from '@ant-design/icons';
import { ServerStatusContext } from '../../../../utils/server-status-context';
import { fetchData, UPDATE_STREAM_KEYS } from '../../../../utils/apis';
const { Title, Paragraph } = Typography;
const { Item } = Form;
const saveKeys = async (keys, setError) => {
try {
await fetchData(UPDATE_STREAM_KEYS, {
method: 'POST',
auth: true,
data: { value: keys },
});
} catch (error) {
console.error(error);
setError(error);
}
};
const AddKeyForm = ({ setShowAddKeyForm, setFieldInConfigState, streamKeys, setError }) => {
const handleAddKey = (newkey: any) => {
const updatedKeys = [...streamKeys, newkey];
console.log(updatedKeys);
setFieldInConfigState({
fieldName: 'streamKeys',
value: updatedKeys,
});
saveKeys(updatedKeys, setError);
setShowAddKeyForm(false);
};
return (
<Form layout="inline" autoComplete="off" onFinish={handleAddKey}>
<Item label="Key" name="key" tooltip="The key you provide your broadcasting software">
<Input placeholder="def456" />
</Item>
<Item label="Comment" name="comment" tooltip="For remembering why you added this key">
<Input placeholder="My OBS Key" />
</Item>
<Button type="primary" htmlType="submit">
Add
</Button>
</Form>
);
};
const AddKeyButton = ({ setShowAddKeyForm }) => (
<Button type="default" onClick={() => setShowAddKeyForm(true)}>
<PlusOutlined />
</Button>
);
const StreamKeys = () => {
const serverStatusData = useContext(ServerStatusContext);
const { serverConfig, setFieldInConfigState } = serverStatusData || {};
const { streamKeys } = serverConfig;
const [showAddKeyForm, setShowAddKeyForm] = useState(false);
const [showKeyMap, setShowKeyMap] = useState({});
const [error, setError] = useState(null);
const handleDeleteKey = keyToRemove => {
const newKeys = streamKeys.filter(k => k !== keyToRemove);
setFieldInConfigState({
fieldName: 'streamKeys',
value: newKeys,
});
saveKeys(newKeys, setError);
};
const handleToggleShowKey = key => {
setShowKeyMap({
...showKeyMap,
[key]: !showKeyMap[key],
});
};
const columns = [
{
title: 'Key',
dataIndex: 'key',
key: 'key',
render: text => (
<Space direction="horizontal">
<Paragraph copyable>{showKeyMap[text] ? text : '**********'}</Paragraph>
<Button
type="link"
style={{ top: '-7px' }}
icon={<EyeOutlined />}
onClick={() => handleToggleShowKey(text)}
/>
</Space>
),
},
{
title: 'Comment',
dataIndex: 'comment',
key: 'comment',
},
{
title: '',
key: 'delete',
render: text => <Button onClick={() => handleDeleteKey(text)} icon={<DeleteOutlined />} />,
},
];
return (
<div>
<Title>Streaming Keys</Title>
<Paragraph>
A streaming key is used with your broadcasting software to authenticate itself to Owncast.
Most people will only need one. However, if you share a server with others or you want
different keys for different broadcasting sources you can add more here.
</Paragraph>
<Paragraph>
These keys are unrelated to the admin password and will not grant you access to make changes
to Owncast&apos;s configuration.
</Paragraph>
<Paragraph>
Read more about broadcasting at{' '}
<a
href="https://owncast.online/docs/broadcasting/?source=admin"
target="_blank"
rel="noopener noreferrer"
>
the documentation
</a>
.
</Paragraph>
<Space direction="vertical" style={{ width: '70%' }}>
{error && <Alert type="error" message="Saving Keys Error" description={error} />}
{streamKeys.length === 0 && (
<Alert
message="No stream keys!"
description="You will not be able to stream until you create at least one stream key and add it to your broadcasting software."
type="error"
/>
)}
<Table
rowKey="key"
columns={columns}
dataSource={streamKeys}
pagination={false}
// eslint-disable-next-line react/no-unstable-nested-components
footer={() =>
showAddKeyForm ? (
<AddKeyForm
setShowAddKeyForm={setShowAddKeyForm}
streamKeys={streamKeys}
setFieldInConfigState={setFieldInConfigState}
setError={setError}
/>
) : (
<AddKeyButton setShowAddKeyForm={setShowAddKeyForm} />
)
}
/>
<br />
</Space>
</div>
);
};
export default StreamKeys;

View File

@ -138,13 +138,19 @@ export interface Health {
representation: number;
}
export interface StreamKey {
key: string;
comment: string;
}
export interface ConfigDetails {
externalActions: ExternalAction[];
ffmpegPath: string;
instanceDetails: ConfigInstanceDetailsFields;
rtmpServerPort: string;
s3: S3Field;
streamKey: string;
streamKeys: StreamKey[];
adminPassword: string;
videoSettings: VideoSettingsFields;
webServerPort: string;
socketHostOverride: string;

View File

@ -108,6 +108,9 @@ export const FEDERATION_ACTIONS = `${API_LOCATION}federation/actions`;
export const API_STREAM_HEALTH_METRICS = `${API_LOCATION}metrics/video`;
// Save an array of stream keys
export const UPDATE_STREAM_KEYS = `${API_LOCATION}config/streamkeys`;
export const API_YP_RESET = `${API_LOCATION}yp/reset`;
export const TEMP_UPDATER_API = LOGS_ALL;

View File

@ -113,13 +113,13 @@ export const TEXTFIELD_PROPS_LOGO = {
label: 'Logo',
tip: 'Upload your logo if you have one. We recommend that you use a square image that is at least 256x256. SVGs are discouraged as they cannot be displayed on all social media platforms.',
};
export const TEXTFIELD_PROPS_STREAM_KEY = {
export const TEXTFIELD_PROPS_ADMIN_PASSWORD = {
apiPath: API_STREAM_KEY,
configPath: '',
maxLength: TEXT_MAXLENGTH,
placeholder: 'abc123',
label: 'Stream Key',
tip: 'Save this key somewhere safe, you will need it to stream or login to the admin dashboard!',
label: 'Admin Password',
tip: 'Save this password somewhere safe, you will need it to login to the admin dashboard!',
required: true,
};
export const TEXTFIELD_PROPS_FFMPEG = {

View File

@ -8,7 +8,8 @@ import { ConfigDetails, UpdateArgs } from '../types/config-section';
import { DEFAULT_VARIANT_STATE } from './config-constants';
export const initialServerConfigState: ConfigDetails = {
streamKey: '',
streamKeys: [],
adminPassword: '',
instanceDetails: {
customStyles: '',
extraPageContent: '',