Skip to content

Commit

Permalink
Merge pull request #357 from Lodestone-Team/#311-and-#267
Browse files Browse the repository at this point in the history
  • Loading branch information
adabingw authored Dec 3, 2023
2 parents 98c0934 + 6d8adc1 commit 5336242
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 81 deletions.
2 changes: 1 addition & 1 deletion core/src/handlers/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ pub async fn change_password(

let requester = users_manager.try_auth_or_err(&token)?;

if requester.uid != config.uid || !requester.can_perform_action(&UserAction::ManageUser) {
if requester.uid != config.uid && !requester.can_perform_action(&UserAction::ManageUser) {
return Err(Error {
kind: ErrorKind::PermissionDenied,
source: eyre!("You are not authorized to change other users password"),
Expand Down
8 changes: 4 additions & 4 deletions dashboard/src/components/Atoms/NotificationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ export default function NotificationCard({
>
<LoadingStatusIcon level={level} state={state} />
<div className="flex flex-col items-start">
<p className="w-full text-medium font-bold tracking-medium">
<p className="w-85 text-medium font-bold tracking-medium break-all">
{title}
</p>
<p className="w-full text-medium font-medium tracking-medium">
<p className="w-85 text-medium font-medium tracking-medium break-all">
{message}
</p>
{!message && (
<span className="whitespace-nowrap text-medium font-medium tracking-medium text-white/50">
{!message && (
<span className="whitespace-nowrap text-medium font-medium tracking-medium text-white/50 break-all">
{formatNotificationTime(timestamp)}
</span>
)}
Expand Down
187 changes: 119 additions & 68 deletions dashboard/src/components/GameConsole.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { faCircle, faServer } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import axios from 'axios';
import { useConsoleStream } from 'data/ConsoleStream';
import { ConsoleEvent, useConsoleStream } from 'data/ConsoleStream';
import { InstanceContext } from 'data/InstanceContext';
import { CommandHistoryContext } from 'data/CommandHistoryContext';
import { useUserAuthorized } from 'data/UserInfo';
import Tooltip from 'rc-tooltip';
import { useContext, useEffect } from 'react';
import { useRef, useState } from 'react';
import { usePrevious } from 'utils/hooks';
import { useLocalStorageQueryParam, usePrevious } from 'utils/hooks';
import { DISABLE_AUTOFILL } from 'utils/util';
import ErrorGraphic from './ErrorGraphic';
import { useDocumentTitle } from 'usehooks-ts';
import Button from './Atoms/Button';
import Checkbox from './Atoms/Checkbox';

const autoScrollThreshold = 10;

Expand All @@ -24,8 +26,15 @@ export default function GameConsole() {
'can_access_instance_console',
uuid
);
const { consoleLog, consoleStatus } = useConsoleStream(uuid);
const defaultFilters = {
"PlayerMessage": true,
"SystemMessage": true,
"InstanceOutput": true
}
const { consoleLog, consoleStatus, clearConsoleLog } = useConsoleStream(uuid);
const [command, setCommand] = useState('');
const [filter, setFilter] = useState('');
const [regex, setRegex] = useState(true);
const { commandHistory, appendCommandHistory } = useContext(
CommandHistoryContext
);
Expand Down Expand Up @@ -128,75 +137,117 @@ export default function GameConsole() {
}
};

const filterMessage = (line: ConsoleEvent) => {
if (filter == '') return true;
if (regex) {
try {
const filterRegex = new RegExp(filter, "i");
if (line.message.match(filterRegex)) return true;
} catch (e) {
console.log("regex invalid!!!");
}
} else {
if (line.message.toLowerCase().indexOf(filter.toLowerCase()) != -1) return true;
}
return false;
}

const checkRegex = (checked: boolean) => {
setRegex(checked)
}

return (
<div className="relative flex h-full w-full grow flex-col rounded-lg border border-gray-faded/30">
<Tooltip
overlay={<span>{consoleStatusMessage}</span>}
placement="bottom"
showArrow={false}
trigger={['hover']}
mouseEnterDelay={0}
>
<FontAwesomeIcon
icon={faCircle}
className={`absolute top-0 right-0 select-none p-1.5 text-small ${consoleStatusColor}`}
/>
</Tooltip>
{!canAccessConsole || consoleStatus === 'no-permission' ? (
<ErrorGraphic
icon={faServer}
message="You don't have permission to access this console"
className="rounded-t-lg border-b border-gray-faded/30"
iconClassName="text-gray-400"
messageClassName="text-white/50"
<div className="relative flex h-full w-full grow flex-col pt-0">
{/* <div className="flex flex-row mb-3 justify-between">
<Button
align="start"
labelGrow={true}
label="clear console"
onClick={() => clearConsoleLog()}
disabled={false}
/>
) : consoleLog.length === 0 ? (
<ErrorGraphic
icon={faServer}
message="No console messages yet"
className="rounded-t-lg border-b border-gray-faded/30"
iconClassName="text-gray-400"
messageClassName="text-white/50"
/>
) : (
<ol
className="font-light flex h-0 grow flex-col overflow-y-auto whitespace-pre-wrap break-words rounded-t-lg border-b border-gray-faded/30 bg-gray-900 py-3 font-mono text-small tracking-tight text-gray-300"
ref={listRef}
>
{consoleLog.map((line) => (
<li
key={line.snowflake}
className="py-[0.125rem] px-4 hover:bg-gray-800"
>
{line.message}
</li>
))}
</ol>
)}
<div className="font-mono text-small">
<form
noValidate
autoComplete={DISABLE_AUTOFILL}
onSubmit={(e: React.SyntheticEvent) => {
e.preventDefault();
sendCommand(command);
appendCommandHistory(command);
setCommandNav((prev) => prev + 1);
setCommand('');
}}
</div> */}
<div className="font-mono text-small mb-3 flex flex-row w-full justify-between">
<input
className="w-full rounded-lg bg-gray-850 py-1 px-4 text-gray-300 outline-white/50 placeholder:text-gray-500 focus-visible:outline focus:outline-none disabled:placeholder:text-gray-500"
placeholder={'Search console...'}
value={filter}
onChange={(e) => setFilter(e.target.value)}
id="search"
type="text"
/>
<Checkbox label='Regex' checked={regex} onChange={checkRegex} className="ml-3"/>
</div>
<div className="relative flex h-full w-full grow flex-col rounded-lg border border-gray-faded/30">
<Tooltip
overlay={<span>{consoleStatusMessage}</span>}
placement="bottom"
showArrow={false}
trigger={['hover']}
mouseEnterDelay={0}
>
<input
className="w-full rounded-b-lg bg-gray-850 py-3 px-4 text-gray-300 outline-white/50 placeholder:text-gray-500 focus-visible:outline focus-visible:outline-2 disabled:placeholder:text-gray-500"
placeholder={consoleInputMessage || 'Enter command...'}
value={command}
onChange={(e) => setCommand(e.target.value)}
id="command"
type="text"
disabled={consoleInputMessage !== ''}
onKeyDown={handleKeyDown}
<FontAwesomeIcon
icon={faCircle}
className={`absolute top-1 right-1 select-none p-1.5 text-small ${consoleStatusColor}`}
/>
</form>
</div>
</Tooltip>
{!canAccessConsole || consoleStatus === 'no-permission' ? (
<ErrorGraphic
icon={faServer}
message="You don't have permission to access this console"
className="border-b border-gray-faded/30"
iconClassName="text-gray-400"
messageClassName="text-white/50"
/>
) : consoleLog.length === 0 ? (
<ErrorGraphic
icon={faServer}
message="No console messages yet"
className="border-b border-gray-faded/30"
iconClassName="text-gray-400"
messageClassName="text-white/50"
/>
) : (
<ol
className="font-light flex h-0 grow rounded-t-lg flex-col overflow-y-auto whitespace-pre-wrap break-words border-b border-gray-faded/30 bg-gray-900 py-3 font-mono text-small tracking-tight text-gray-300"
ref={listRef}
>
{consoleLog.map((line) => {
return filterMessage(line) ?
<li
key={line.snowflake}
className="py-[0.125rem] px-4 hover:bg-gray-800"
>
{line.message}
</li> : <li></li>
})}
</ol>
)}
<div className="font-mono text-small">
<form
noValidate
autoComplete={DISABLE_AUTOFILL}
onSubmit={(e: React.SyntheticEvent) => {
e.preventDefault();
sendCommand(command);
appendCommandHistory(command);
setCommandNav((prev) => prev + 1);
setCommand('');
}}
>
<input
className="w-full rounded-b-lg bg-gray-850 py-3 px-4 text-gray-300 outline-white/50 focus:outline-none placeholder:text-gray-500 focus-visible:outline focus-visible:outline-2 disabled:placeholder:text-gray-500"
placeholder={consoleInputMessage || 'Enter command...'}
value={command}
onChange={(e) => setCommand(e.target.value)}
id="command"
type="text"
disabled={consoleInputMessage !== ''}
onKeyDown={handleKeyDown}
/>
</form>
</div>
</div>
</div>
);
}
6 changes: 1 addition & 5 deletions dashboard/src/components/UserBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,8 @@ export default function UserBox({
<div className="flex min-h-full items-center justify-center p-4">
<Dialog.Panel className="flex w-[500px] flex-col items-stretch justify-center gap-4 rounded-3xl bg-gray-800 px-8 pb-8 pt-16">
<h1 className="text-h1 font-bold tracking-tight text-gray-300">
Create a new user account
Change password
</h1>
<p>
This user will start with no permissions. You can grant them
permissions later.
</p>
{isSelf ? (
<ChangeSelfPasswordForm
onSuccess={() => setShowChangePassword(false)}
Expand Down
8 changes: 7 additions & 1 deletion dashboard/src/data/ConsoleStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ export const useConsoleStream = (uuid: string) => {
uuid
);

const clearConsoleLog = () => {
const econsoleLog: ConsoleEvent[] = []
setConsoleLog(econsoleLog)
}

const mergeConsoleLog = (newLog: ClientEvent[]) => {
setConsoleLog((oldLog) => {
const consoleEvents = newLog
Expand All @@ -99,7 +104,6 @@ export const useConsoleStream = (uuid: string) => {
);
})
.map(toConsoleEvent);

const mergedLog = [...oldLog, ...consoleEvents];
// this is slow ik
return mergedLog.filter(
Expand Down Expand Up @@ -135,6 +139,7 @@ export const useConsoleStream = (uuid: string) => {

websocket.onclose = (event) => {
setStatus(event.code === 1000 ? 'closed' : 'error');
console.log("event: ", event)
};

return () => {
Expand Down Expand Up @@ -162,5 +167,6 @@ export const useConsoleStream = (uuid: string) => {
return {
consoleLog,
consoleStatus: status,
clearConsoleLog
};
};
2 changes: 1 addition & 1 deletion dashboard/src/pages/InstanceTabs/InstanceTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ const InstanceTabs = () => {
className="gutter-stable -mx-3 flex grow flex-row items-stretch overflow-y-auto pl-4 pr-2"
key={`${instance.name}-${tab.title}`}
>
<div className="flex h-fit min-h-full w-full flex-col gap-12 pt-6 pb-10 focus:outline-none">
<div className="flex h-fit min-h-full w-full flex-col gap-2 pt-6 pb-10 focus:outline-none">
{tab.displayTitle && (
<div className="flex font-title text-h1 font-bold leading-tight text-gray-300">
{tab.displayTitle}
Expand Down
3 changes: 2 additions & 1 deletion dashboard/src/pages/settings/UserSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ export const UserSettings = () => {
disabled: boolean
) =>
selectedUser && (
<div className="flex w-full flex-col gap-10">
<div className="flex w-full flex-col gap-10 mb-10">
{permissionList.map((permission) => {
const currentSettings =
selectedUser.permissions[permission.permission];
Expand Down Expand Up @@ -245,6 +245,7 @@ export const UserSettings = () => {
optionKey={(uuid) => uuid}
onChange={(newSettings) => {
// I hate typescript
// |- me too
const newPermissions = {
...selectedUser.permissions,
[permission.permission]: newSettings,
Expand Down

0 comments on commit 5336242

Please sign in to comment.