Skip to content

Commit d69f816

Browse files
committed
Add handler to fetch all of the system permissions and load them into the state
1 parent 867dbf3 commit d69f816

File tree

8 files changed

+106
-6
lines changed

8 files changed

+106
-6
lines changed

app/Http/Controllers/Api/Client/ClientController.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
namespace Pterodactyl\Http\Controllers\Api\Client;
44

55
use Pterodactyl\Models\User;
6+
use Illuminate\Support\Collection;
7+
use Pterodactyl\Models\Permission;
68
use Pterodactyl\Repositories\Eloquent\ServerRepository;
79
use Pterodactyl\Transformers\Api\Client\ServerTransformer;
810
use Pterodactyl\Http\Requests\Api\Client\GetServersRequest;
@@ -62,4 +64,25 @@ public function index(GetServersRequest $request): array
6264
->transformWith($this->getTransformer(ServerTransformer::class))
6365
->toArray();
6466
}
67+
68+
/**
69+
* Returns all of the subuser permissions available on the system.
70+
*
71+
* @return array
72+
*/
73+
public function permissions()
74+
{
75+
$permissions = Permission::permissions()->map(function ($values, $key) {
76+
return Collection::make($values)->map(function ($permission) use ($key) {
77+
return $key . '.' . $permission;
78+
})->values()->toArray();
79+
})->flatten();
80+
81+
return [
82+
'object' => 'system_permissions',
83+
'attributes' => [
84+
'permissions' => $permissions,
85+
],
86+
];
87+
}
6588
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { SubuserPermission } from '@/state/server/subusers';
2+
import http from '@/api/http';
3+
4+
export default (): Promise<SubuserPermission[]> => {
5+
return new Promise((resolve, reject) => {
6+
http.get(`/api/client/permissions`)
7+
.then(({ data }) => resolve(data.attributes.permissions))
8+
.catch(reject);
9+
});
10+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import { SubuserPermission } from '@/state/server/subusers';
3+
4+
interface Props {
5+
defaultPermissions: SubuserPermission[];
6+
}
7+
8+
export default ({ defaultPermissions }: Props) => {
9+
return null;
10+
};

resources/scripts/components/server/users/UsersContainer.tsx

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { ServerContext } from '@/state/server';
55
import Spinner from '@/components/elements/Spinner';
66
import { Subuser } from '@/state/server/subusers';
77
import { CSSTransition } from 'react-transition-group';
8+
import classNames from 'classnames';
9+
import PermissionEditor from '@/components/server/users/PermissionEditor';
10+
import { Actions, useStoreActions, useStoreState } from 'easy-peasy';
11+
import { ApplicationStore } from '@/state';
812

913
export default () => {
1014
const [ loading, setLoading ] = useState(true);
@@ -14,6 +18,15 @@ export default () => {
1418
const subusers = ServerContext.useStoreState(state => state.subusers.data);
1519
const getSubusers = ServerContext.useStoreActions(actions => actions.subusers.getSubusers);
1620

21+
const permissions = useStoreState((state: ApplicationStore) => state.permissions.data);
22+
const getPermissions = useStoreActions((actions: Actions<ApplicationStore>) => actions.permissions.getPermissions);
23+
24+
useEffect(() => {
25+
if (!permissions.length) {
26+
getPermissions().catch(error => console.error(error));
27+
}
28+
}, [ permissions, getPermissions ]);
29+
1730
useEffect(() => {
1831
getSubusers(uuid)
1932
.then(() => setLoading(false))
@@ -32,8 +45,11 @@ export default () => {
3245
<div className={'flex my-10'}>
3346
<div className={'w-1/2'}>
3447
<h2 className={'text-neutral-300 mb-4'}>Subusers</h2>
35-
<div className={'border-t-4 border-primary-400 grey-box mt-0'}>
36-
{loading ?
48+
<div className={classNames('border-t-4 grey-box mt-0', {
49+
'border-cyan-400': editSubuser === null,
50+
'border-neutral-400': editSubuser !== null,
51+
})}>
52+
{(loading || !permissions.length) ?
3753
<div className={'w-full'}>
3854
<Spinner centered={true}/>
3955
</div>
@@ -78,8 +94,10 @@ export default () => {
7894
<CSSTransition timeout={250} classNames={'fade'} appear={true} in={true}>
7995
<div className={'flex-1 ml-6'}>
8096
<h2 className={'text-neutral-300 mb-4'}>Edit {editSubuser.email}</h2>
81-
<div className={'border-t-4 border-primary-400 grey-box mt-0'}>
82-
<p>Edit permissions here.</p>
97+
<div className={'border-t-4 border-cyan-400 grey-box mt-0'}>
98+
<PermissionEditor
99+
defaultPermissions={editSubuser.permissions}
100+
/>
83101
</div>
84102
</div>
85103
</CSSTransition>

resources/scripts/state/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { createStore } from 'easy-peasy';
22
import flashes, { FlashStore } from '@/state/flashes';
33
import user, { UserStore } from '@/state/user';
4+
import permissions, { GloablPermissionsStore } from '@/state/permissions';
45

56
export interface ApplicationStore {
7+
permissions: GloablPermissionsStore;
68
flashes: FlashStore;
79
user: UserStore;
810
}
911

1012
const state: ApplicationStore = {
13+
permissions,
1114
flashes,
1215
user,
1316
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { SubuserPermission } from '@/state/server/subusers';
2+
import { action, Action, thunk, Thunk } from 'easy-peasy';
3+
import getSystemPermissions from '@/api/getSystemPermissions';
4+
5+
export interface GloablPermissionsStore {
6+
data: SubuserPermission[];
7+
setPermissions: Action<GloablPermissionsStore, SubuserPermission[]>;
8+
getPermissions: Thunk<GloablPermissionsStore, void, {}, any, Promise<void>>;
9+
}
10+
11+
const permissions: GloablPermissionsStore = {
12+
data: [],
13+
14+
setPermissions: action((state, payload) => {
15+
state.data = payload;
16+
}),
17+
18+
getPermissions: thunk(async (actions) => {
19+
const permissions = await getSystemPermissions();
20+
21+
actions.setPermissions(permissions);
22+
}),
23+
};
24+
25+
export default permissions;

resources/scripts/state/server/subusers.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
import { action, Action, thunk, Thunk } from 'easy-peasy';
22
import getServerSubusers from '@/api/server/users/getServerSubusers';
33

4-
export type SubuserPermission = string;
4+
export type SubuserPermission =
5+
'websocket.*' |
6+
'control.console' | 'control.start' | 'control.stop' | 'control.restart' | 'control.kill' |
7+
'user.create' | 'user.read' | 'user.update' | 'user.delete' |
8+
'file.create' | 'file.read' | 'file.update' | 'file.delete' | 'file.archive' | 'file.sftp' |
9+
'allocation.read' | 'allocation.update' |
10+
'startup.read' | 'startup.update' |
11+
'database.create' | 'database.read' | 'database.update' | 'database.delete' | 'database.view_password' |
12+
'schedule.create' | 'schedule.read' | 'schedule.update' | 'schedule.delete'
13+
;
514

615
export interface Subuser {
716
uuid: string;
@@ -30,7 +39,7 @@ const subusers: ServerSubuserStore = {
3039
}),
3140

3241
appendSubuser: action((state, payload) => {
33-
state.data = [...state.data, payload];
42+
state.data = [ ...state.data, payload ];
3443
}),
3544

3645
getSubusers: thunk(async (actions, payload) => {

routes/api-client.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<?php
22

3+
use Illuminate\Support\Facades\Route;
34
use Pterodactyl\Http\Middleware\Api\Client\Server\AuthenticateServerAccess;
45

56
/*
@@ -11,6 +12,7 @@
1112
|
1213
*/
1314
Route::get('/', 'ClientController@index')->name('api.client.index');
15+
Route::get('/permissions', 'ClientController@permissions');
1416

1517
Route::group(['prefix' => '/account'], function () {
1618
Route::get('/', 'AccountController@index')->name('api.client.account');

0 commit comments

Comments
 (0)