From d69f816d9d52ee0b09f67684ee2e504d00700795 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sun, 3 Nov 2019 17:37:06 -0800 Subject: [PATCH] Add handler to fetch all of the system permissions and load them into the state --- .../Api/Client/ClientController.php | 23 ++++++++++++++++ resources/scripts/api/getSystemPermissions.ts | 10 +++++++ .../server/users/PermissionEditor.tsx | 10 +++++++ .../server/users/UsersContainer.tsx | 26 ++++++++++++++++--- resources/scripts/state/index.ts | 3 +++ resources/scripts/state/permissions.ts | 25 ++++++++++++++++++ resources/scripts/state/server/subusers.ts | 13 ++++++++-- routes/api-client.php | 2 ++ 8 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 resources/scripts/api/getSystemPermissions.ts create mode 100644 resources/scripts/components/server/users/PermissionEditor.tsx create mode 100644 resources/scripts/state/permissions.ts diff --git a/app/Http/Controllers/Api/Client/ClientController.php b/app/Http/Controllers/Api/Client/ClientController.php index 828792c95..f11d1ac15 100644 --- a/app/Http/Controllers/Api/Client/ClientController.php +++ b/app/Http/Controllers/Api/Client/ClientController.php @@ -3,6 +3,8 @@ namespace Pterodactyl\Http\Controllers\Api\Client; use Pterodactyl\Models\User; +use Illuminate\Support\Collection; +use Pterodactyl\Models\Permission; use Pterodactyl\Repositories\Eloquent\ServerRepository; use Pterodactyl\Transformers\Api\Client\ServerTransformer; use Pterodactyl\Http\Requests\Api\Client\GetServersRequest; @@ -62,4 +64,25 @@ class ClientController extends ClientApiController ->transformWith($this->getTransformer(ServerTransformer::class)) ->toArray(); } + + /** + * Returns all of the subuser permissions available on the system. + * + * @return array + */ + public function permissions() + { + $permissions = Permission::permissions()->map(function ($values, $key) { + return Collection::make($values)->map(function ($permission) use ($key) { + return $key . '.' . $permission; + })->values()->toArray(); + })->flatten(); + + return [ + 'object' => 'system_permissions', + 'attributes' => [ + 'permissions' => $permissions, + ], + ]; + } } diff --git a/resources/scripts/api/getSystemPermissions.ts b/resources/scripts/api/getSystemPermissions.ts new file mode 100644 index 000000000..47016b3c9 --- /dev/null +++ b/resources/scripts/api/getSystemPermissions.ts @@ -0,0 +1,10 @@ +import { SubuserPermission } from '@/state/server/subusers'; +import http from '@/api/http'; + +export default (): Promise => { + return new Promise((resolve, reject) => { + http.get(`/api/client/permissions`) + .then(({ data }) => resolve(data.attributes.permissions)) + .catch(reject); + }); +}; diff --git a/resources/scripts/components/server/users/PermissionEditor.tsx b/resources/scripts/components/server/users/PermissionEditor.tsx new file mode 100644 index 000000000..d2525681a --- /dev/null +++ b/resources/scripts/components/server/users/PermissionEditor.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { SubuserPermission } from '@/state/server/subusers'; + +interface Props { + defaultPermissions: SubuserPermission[]; +} + +export default ({ defaultPermissions }: Props) => { + return null; +}; diff --git a/resources/scripts/components/server/users/UsersContainer.tsx b/resources/scripts/components/server/users/UsersContainer.tsx index a66cf0395..8a3aa77bb 100644 --- a/resources/scripts/components/server/users/UsersContainer.tsx +++ b/resources/scripts/components/server/users/UsersContainer.tsx @@ -5,6 +5,10 @@ import { ServerContext } from '@/state/server'; import Spinner from '@/components/elements/Spinner'; import { Subuser } from '@/state/server/subusers'; import { CSSTransition } from 'react-transition-group'; +import classNames from 'classnames'; +import PermissionEditor from '@/components/server/users/PermissionEditor'; +import { Actions, useStoreActions, useStoreState } from 'easy-peasy'; +import { ApplicationStore } from '@/state'; export default () => { const [ loading, setLoading ] = useState(true); @@ -14,6 +18,15 @@ export default () => { const subusers = ServerContext.useStoreState(state => state.subusers.data); const getSubusers = ServerContext.useStoreActions(actions => actions.subusers.getSubusers); + const permissions = useStoreState((state: ApplicationStore) => state.permissions.data); + const getPermissions = useStoreActions((actions: Actions) => actions.permissions.getPermissions); + + useEffect(() => { + if (!permissions.length) { + getPermissions().catch(error => console.error(error)); + } + }, [ permissions, getPermissions ]); + useEffect(() => { getSubusers(uuid) .then(() => setLoading(false)) @@ -32,8 +45,11 @@ export default () => {

Subusers

-
- {loading ? +
+ {(loading || !permissions.length) ?
@@ -78,8 +94,10 @@ export default () => {

Edit {editSubuser.email}

-
-

Edit permissions here.

+
+
diff --git a/resources/scripts/state/index.ts b/resources/scripts/state/index.ts index db3181aa5..0a9f7e6f7 100644 --- a/resources/scripts/state/index.ts +++ b/resources/scripts/state/index.ts @@ -1,13 +1,16 @@ import { createStore } from 'easy-peasy'; import flashes, { FlashStore } from '@/state/flashes'; import user, { UserStore } from '@/state/user'; +import permissions, { GloablPermissionsStore } from '@/state/permissions'; export interface ApplicationStore { + permissions: GloablPermissionsStore; flashes: FlashStore; user: UserStore; } const state: ApplicationStore = { + permissions, flashes, user, }; diff --git a/resources/scripts/state/permissions.ts b/resources/scripts/state/permissions.ts new file mode 100644 index 000000000..e275e38f5 --- /dev/null +++ b/resources/scripts/state/permissions.ts @@ -0,0 +1,25 @@ +import { SubuserPermission } from '@/state/server/subusers'; +import { action, Action, thunk, Thunk } from 'easy-peasy'; +import getSystemPermissions from '@/api/getSystemPermissions'; + +export interface GloablPermissionsStore { + data: SubuserPermission[]; + setPermissions: Action; + getPermissions: Thunk>; +} + +const permissions: GloablPermissionsStore = { + data: [], + + setPermissions: action((state, payload) => { + state.data = payload; + }), + + getPermissions: thunk(async (actions) => { + const permissions = await getSystemPermissions(); + + actions.setPermissions(permissions); + }), +}; + +export default permissions; diff --git a/resources/scripts/state/server/subusers.ts b/resources/scripts/state/server/subusers.ts index 758e704cf..5d15149b7 100644 --- a/resources/scripts/state/server/subusers.ts +++ b/resources/scripts/state/server/subusers.ts @@ -1,7 +1,16 @@ import { action, Action, thunk, Thunk } from 'easy-peasy'; import getServerSubusers from '@/api/server/users/getServerSubusers'; -export type SubuserPermission = string; +export type SubuserPermission = + 'websocket.*' | + 'control.console' | 'control.start' | 'control.stop' | 'control.restart' | 'control.kill' | + 'user.create' | 'user.read' | 'user.update' | 'user.delete' | + 'file.create' | 'file.read' | 'file.update' | 'file.delete' | 'file.archive' | 'file.sftp' | + 'allocation.read' | 'allocation.update' | + 'startup.read' | 'startup.update' | + 'database.create' | 'database.read' | 'database.update' | 'database.delete' | 'database.view_password' | + 'schedule.create' | 'schedule.read' | 'schedule.update' | 'schedule.delete' + ; export interface Subuser { uuid: string; @@ -30,7 +39,7 @@ const subusers: ServerSubuserStore = { }), appendSubuser: action((state, payload) => { - state.data = [...state.data, payload]; + state.data = [ ...state.data, payload ]; }), getSubusers: thunk(async (actions, payload) => { diff --git a/routes/api-client.php b/routes/api-client.php index 6862227e6..5e54f8cf4 100644 --- a/routes/api-client.php +++ b/routes/api-client.php @@ -1,5 +1,6 @@ name('api.client.index'); +Route::get('/permissions', 'ClientController@permissions'); Route::group(['prefix' => '/account'], function () { Route::get('/', 'AccountController@index')->name('api.client.account');