Merge branch 'develop' into feature/react-admin
This commit is contained in:
commit
5636c25838
14 changed files with 90 additions and 108 deletions
|
@ -57,7 +57,7 @@ class SendPasswordReset extends Notification implements ShouldQueue
|
|||
return (new MailMessage)
|
||||
->subject('Reset Password')
|
||||
->line('You are receiving this email because we received a password reset request for your account.')
|
||||
->action('Reset Password', url('/auth/password/reset/' . $this->token . '?email=' . $notifiable->email))
|
||||
->action('Reset Password', url('/auth/password/reset/' . $this->token . '?email=' . urlencode($notifiable->email)))
|
||||
->line('If you did not request a password reset, no further action is required.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"author": "support@pterodactyl.io",
|
||||
"description": "For a long time, Minecraft server owners have had a dream that encompasses a free, easy, and reliable way to connect multiple Minecraft servers together. BungeeCord is the answer to said dream. Whether you are a small server wishing to string multiple game-modes together, or the owner of the ShotBow Network, BungeeCord is the ideal solution for you. With the help of BungeeCord, you will be able to unlock your community's full potential.",
|
||||
"features": ["eula"],
|
||||
"image": "quay.io\/pterodactyl\/core:java",
|
||||
"images": ["quay.io\/pterodactyl\/core:java", "quay.io\/pterodactyl\/core:java-11"],
|
||||
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}",
|
||||
"config": {
|
||||
"files": "{\r\n \"config.yml\": {\r\n \"parser\": \"yaml\",\r\n \"find\": {\r\n \"listeners[0].query_enabled\": true,\r\n \"listeners[0].query_port\": \"{{server.build.default.port}}\",\r\n \"listeners[0].host\": \"0.0.0.0:{{server.build.default.port}}\",\r\n \"servers.*.address\": {\r\n \"regex:^(127\\\\.0\\\\.0\\\\.1|localhost)(:\\\\d{1,5})?$\": \"{{config.docker.interface}}$2\"\r\n }\r\n }\r\n }\r\n}",
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"author": "support@pterodactyl.io",
|
||||
"description": "Minecraft Forge Server. Minecraft Forge is a modding API (Application Programming Interface), which makes it easier to create mods, and also make sure mods are compatible with each other.",
|
||||
"features": ["eula"],
|
||||
"image": "quay.io\/pterodactyl\/core:java",
|
||||
"images": ["quay.io\/pterodactyl\/core:java", "quay.io\/pterodactyl\/core:java-11"],
|
||||
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}",
|
||||
"config": {
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"enable-query\": \"true\",\r\n \"server-port\": \"{{server.build.default.port}}\",\r\n \"query.port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
|
@ -61,4 +61,4 @@
|
|||
"rules": "nullable|string|max:20"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"author": "parker@pterodactyl.io",
|
||||
"description": "High performance Spigot fork that aims to fix gameplay and mechanics inconsistencies.",
|
||||
"features": ["eula"],
|
||||
"image": "quay.io\/pterodactyl\/core:java-11",
|
||||
"images": ["quay.io\/pterodactyl\/core:java-11", "quay.io\/pterodactyl\/core:java"],
|
||||
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -Dterminal.jline=false -Dterminal.ansi=true -jar {{SERVER_JARFILE}}",
|
||||
"config": {
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"author": "support@pterodactyl.io",
|
||||
"description": "SpongeVanilla is the SpongeAPI implementation for Vanilla Minecraft.",
|
||||
"features": ["eula"],
|
||||
"image": "quay.io\/pterodactyl\/core:java-glibc",
|
||||
"images": ["quay.io\/pterodactyl\/core:java-glibc"],
|
||||
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}",
|
||||
"config": {
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"enable-query\": \"true\",\r\n \"server-port\": \"{{server.build.default.port}}\",\r\n \"query.port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"author": "support@pterodactyl.io",
|
||||
"description": "Minecraft is a game about placing blocks and going on adventures. Explore randomly generated worlds and build amazing things from the simplest of homes to the grandest of castles. Play in Creative Mode with unlimited resources or mine deep in Survival Mode, crafting weapons and armor to fend off dangerous mobs. Do all this alone or with friends.",
|
||||
"features": ["eula"],
|
||||
"image": "quay.io\/pterodactyl\/core:java",
|
||||
"images": ["quay.io\/pterodactyl\/core:java", "quay.io\/pterodactyl\/core:java-11"],
|
||||
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}",
|
||||
"config": {
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"enable-query\": \"true\",\r\n \"server-port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import React, { useRef } from 'react';
|
||||
import React from 'react';
|
||||
import { Route } from 'react-router';
|
||||
import { SwitchTransition } from 'react-transition-group';
|
||||
import Fade from '@/components/elements/Fade';
|
||||
import styled from 'styled-components/macro';
|
||||
import tw from 'twin.macro';
|
||||
import v4 from 'uuid/v4';
|
||||
|
||||
const StyledSwitchTransition = styled(SwitchTransition)`
|
||||
${tw`relative`};
|
||||
|
@ -15,13 +14,11 @@ const StyledSwitchTransition = styled(SwitchTransition)`
|
|||
`;
|
||||
|
||||
const TransitionRouter: React.FC = ({ children }) => {
|
||||
const uuid = useRef(v4()).current;
|
||||
|
||||
return (
|
||||
<Route
|
||||
render={({ location }) => (
|
||||
<StyledSwitchTransition>
|
||||
<Fade timeout={150} key={location.key || uuid} in appear unmountOnExit>
|
||||
<Fade timeout={150} key={location.pathname + location.search} in appear unmountOnExit>
|
||||
<section>
|
||||
{children}
|
||||
</section>
|
||||
|
|
|
@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
|||
import getServerSchedules from '@/api/server/schedules/getServerSchedules';
|
||||
import { ServerContext } from '@/state/server';
|
||||
import Spinner from '@/components/elements/Spinner';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { useHistory, useRouteMatch } from 'react-router-dom';
|
||||
import FlashMessageRender from '@/components/FlashMessageRender';
|
||||
import ScheduleRow from '@/components/server/schedules/ScheduleRow';
|
||||
import { httpErrorToHuman } from '@/api/http';
|
||||
|
@ -14,7 +14,10 @@ import GreyRowBox from '@/components/elements/GreyRowBox';
|
|||
import Button from '@/components/elements/Button';
|
||||
import ServerContentBlock from '@/components/elements/ServerContentBlock';
|
||||
|
||||
export default ({ match, history }: RouteComponentProps) => {
|
||||
export default () => {
|
||||
const match = useRouteMatch();
|
||||
const history = useHistory();
|
||||
|
||||
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
||||
const { clearFlashes, addError } = useFlash();
|
||||
const [ loading, setLoading ] = useState(true);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { useHistory, useLocation, useParams } from 'react-router-dom';
|
||||
import { Schedule } from '@/api/server/schedules/getServerSchedules';
|
||||
import getServerSchedule from '@/api/server/schedules/getServerSchedule';
|
||||
import Spinner from '@/components/elements/Spinner';
|
||||
|
@ -45,7 +45,11 @@ const ActivePill = ({ active }: { active: boolean }) => (
|
|||
</span>
|
||||
);
|
||||
|
||||
export default ({ match, history, location: { state } }: RouteComponentProps<Params, Record<string, unknown>, State>) => {
|
||||
export default () => {
|
||||
const params = useParams() as Params;
|
||||
const history = useHistory();
|
||||
const state: State = useLocation().state;
|
||||
|
||||
const id = ServerContext.useStoreState(state => state.server.data!.id);
|
||||
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
||||
|
||||
|
@ -57,20 +61,20 @@ export default ({ match, history, location: { state } }: RouteComponentProps<Par
|
|||
const appendSchedule = ServerContext.useStoreActions(actions => actions.schedules.appendSchedule);
|
||||
|
||||
useEffect(() => {
|
||||
if (schedule?.id === Number(match.params.id)) {
|
||||
if (schedule?.id === Number(params.id)) {
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
clearFlashes('schedules');
|
||||
getServerSchedule(uuid, Number(match.params.id))
|
||||
getServerSchedule(uuid, Number(params.id))
|
||||
.then(schedule => appendSchedule(schedule))
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
clearAndAddHttpError({ error, key: 'schedules' });
|
||||
})
|
||||
.then(() => setIsLoading(false));
|
||||
}, [ match ]);
|
||||
}, [ params ]);
|
||||
|
||||
const toggleEditModal = useCallback(() => {
|
||||
setShowEditModal(s => !s);
|
||||
|
|
|
@ -48,7 +48,7 @@ export default () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<ServerContentBlock title={'Subusers'}>
|
||||
<ServerContentBlock title={'Users'}>
|
||||
<FlashMessageRender byKey={'users'} css={tw`mb-4`}/>
|
||||
{!subusers.length ?
|
||||
<p css={tw`text-center text-sm text-neutral-300`}>
|
||||
|
|
25
resources/scripts/hoc/RequireServerPermission.tsx
Normal file
25
resources/scripts/hoc/RequireServerPermission.tsx
Normal file
|
@ -0,0 +1,25 @@
|
|||
import React from 'react';
|
||||
import Can from '@/components/elements/Can';
|
||||
import ScreenBlock from '@/components/screens/ScreenBlock';
|
||||
export interface RequireServerPermissionProps {
|
||||
permissions: string | string[]
|
||||
}
|
||||
|
||||
const RequireServerPermission: React.FC<RequireServerPermissionProps> = ({ children, permissions }) => {
|
||||
return (
|
||||
<Can
|
||||
action={permissions}
|
||||
renderOnError={
|
||||
<ScreenBlock
|
||||
image={'/assets/svgs/server_error.svg'}
|
||||
title={'Access Denied'}
|
||||
message={'You do not have permission to access this page.'}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</Can>
|
||||
);
|
||||
};
|
||||
|
||||
export default RequireServerPermission;
|
|
@ -1,31 +0,0 @@
|
|||
import React from 'react';
|
||||
import Can from '@/components/elements/Can';
|
||||
import ScreenBlock from '@/components/screens/ScreenBlock';
|
||||
import isEqual from 'react-fast-compare';
|
||||
|
||||
const requireServerPermission = (Component: React.ComponentType<any>, permissions: string | string[]) => {
|
||||
return class extends React.Component<any, any> {
|
||||
shouldComponentUpdate (nextProps: Readonly<any>) {
|
||||
return !isEqual(nextProps, this.props);
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<Can
|
||||
action={permissions}
|
||||
renderOnError={
|
||||
<ScreenBlock
|
||||
image={'/assets/svgs/server_error.svg'}
|
||||
title={'Access Denied'}
|
||||
message={'You do not have permission to access this page.'}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<Component {...this.props}/>
|
||||
</Can>
|
||||
);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export default requireServerPermission;
|
|
@ -27,10 +27,10 @@ import SubNavigation from '@/components/elements/SubNavigation';
|
|||
import NetworkContainer from '@/components/server/network/NetworkContainer';
|
||||
import InstallListener from '@/components/server/InstallListener';
|
||||
import StartupContainer from '@/components/server/startup/StartupContainer';
|
||||
import requireServerPermission from '@/hoc/requireServerPermission';
|
||||
import ErrorBoundary from '@/components/elements/ErrorBoundary';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import RequireServerPermission from '@/hoc/RequireServerPermission';
|
||||
|
||||
const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => {
|
||||
const rootAdmin = useStoreState(state => state.user.data!.rootAdmin);
|
||||
|
@ -142,50 +142,44 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
|
|||
<TransitionRouter>
|
||||
<Switch location={location}>
|
||||
<Route path={`${match.path}`} component={ServerConsole} exact/>
|
||||
<Route
|
||||
path={`${match.path}/files`}
|
||||
component={requireServerPermission(FileManagerContainer, 'file.*')}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path={`${match.path}/files/:action(edit|new)`}
|
||||
render={props => (
|
||||
<SuspenseSpinner>
|
||||
<FileEditContainer {...props as any}/>
|
||||
</SuspenseSpinner>
|
||||
)}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path={`${match.path}/databases`}
|
||||
component={requireServerPermission(DatabasesContainer, 'database.*')}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path={`${match.path}/schedules`}
|
||||
component={requireServerPermission(ScheduleContainer, 'schedule.*')}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path={`${match.path}/schedules/:id`}
|
||||
component={ScheduleEditContainer}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path={`${match.path}/users`}
|
||||
component={requireServerPermission(UsersContainer, 'user.*')}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path={`${match.path}/backups`}
|
||||
component={requireServerPermission(BackupContainer, 'backup.*')}
|
||||
exact
|
||||
/>
|
||||
<Route
|
||||
path={`${match.path}/network`}
|
||||
component={requireServerPermission(NetworkContainer, 'allocation.*')}
|
||||
exact
|
||||
/>
|
||||
<Route path={`${match.path}/files`} exact>
|
||||
<RequireServerPermission permissions={'file.*'}>
|
||||
<FileManagerContainer />
|
||||
</RequireServerPermission>
|
||||
</Route>
|
||||
<Route path={`${match.path}/files/:action(edit|new)`} exact>
|
||||
<SuspenseSpinner>
|
||||
<FileEditContainer />
|
||||
</SuspenseSpinner>
|
||||
</Route>
|
||||
<Route path={`${match.path}/databases`} exact>
|
||||
<RequireServerPermission permissions={'database.*'}>
|
||||
<DatabasesContainer />
|
||||
</RequireServerPermission>
|
||||
</Route>
|
||||
<Route path={`${match.path}/schedules`} exact>
|
||||
<RequireServerPermission permissions={'schedule.*'}>
|
||||
<ScheduleContainer />
|
||||
</RequireServerPermission>
|
||||
</Route>
|
||||
<Route path={`${match.path}/schedules/:id`} exact>
|
||||
<ScheduleEditContainer/>
|
||||
</Route>
|
||||
<Route path={`${match.path}/users`} exact>
|
||||
<RequireServerPermission permissions={'user.*'}>
|
||||
<UsersContainer />
|
||||
</RequireServerPermission>
|
||||
</Route>
|
||||
<Route path={`${match.path}/backups`} exact>
|
||||
<RequireServerPermission permissions={'backup.*'}>
|
||||
<BackupContainer />
|
||||
</RequireServerPermission>
|
||||
</Route>
|
||||
<Route path={`${match.path}/network`} exact>
|
||||
<RequireServerPermission permissions={'allocation.*'}>
|
||||
<NetworkContainer />
|
||||
</RequireServerPermission>
|
||||
</Route>
|
||||
<Route path={`${match.path}/startup`} component={StartupContainer} exact/>
|
||||
<Route path={`${match.path}/settings`} component={SettingsContainer} exact/>
|
||||
<Route path={'*'} component={NotFound}/>
|
||||
|
|
14
yarn.lock
14
yarn.lock
|
@ -2166,19 +2166,9 @@ camelize@^1.0.0:
|
|||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
|
||||
|
||||
caniuse-lite@^1.0.30001088:
|
||||
version "1.0.30001093"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001093.tgz#833e80f64b1a0455cbceed2a4a3baf19e4abd312"
|
||||
integrity sha512-0+ODNoOjtWD5eS9aaIpf4K0gQqZfILNY4WSNuYzeT1sXni+lMrrVjc0odEobJt6wrODofDZUX8XYi/5y7+xl8g==
|
||||
|
||||
caniuse-lite@^1.0.30001135:
|
||||
version "1.0.30001148"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001148.tgz#dc97c7ed918ab33bf8706ddd5e387287e015d637"
|
||||
integrity sha512-E66qcd0KMKZHNJQt9hiLZGE3J4zuTqE1OnU53miEVtylFbwOEmeA5OsRu90noZful+XGSQOni1aT2tiqu/9yYw==
|
||||
|
||||
caniuse-lite@^1.0.30001165:
|
||||
caniuse-lite@^1.0.30001088, caniuse-lite@^1.0.30001135, caniuse-lite@^1.0.30001165:
|
||||
version "1.0.30001170"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001170.tgz#0088bfecc6a14694969e391cc29d7eb6362ca6a7"
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001170.tgz"
|
||||
integrity sha512-Dd4d/+0tsK0UNLrZs3CvNukqalnVTRrxb5mcQm8rHL49t7V5ZaTygwXkrq+FB+dVDf++4ri8eJnFEJAB8332PA==
|
||||
|
||||
chalk@^2.0, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
|
||||
|
|
Loading…
Reference in a new issue