Skip to content

Commit 05478e3

Browse files
committed
Merge branch 'feature/vuejs' into feature/vue-serverview
2 parents 855af7c + f971cdf commit 05478e3

File tree

29 files changed

+3064
-16284
lines changed

29 files changed

+3064
-16284
lines changed

.dev/vagrant/provision.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ debconf-set-selections <<< 'mariadb-server-5.5 mysql-server/root_password_again
2121
# actually install
2222
apt-get install -y php7.2 php7.2-cli php7.2-gd php7.2-mysql php7.2-pdo php7.2-mbstring php7.2-tokenizer php7.2-bcmath php7.2-xml php7.2-fpm php7.2-memcached php7.2-curl php7.2-zip php-xdebug mariadb-server nginx curl tar unzip git memcached > /dev/null
2323

24+
echo "Install nodejs and yarn"
25+
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
26+
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
27+
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
28+
apt-get -y install nodejs yarn > /dev/null
29+
2430
echo "Install composer"
2531
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
2632

BUILDING.md

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,57 @@
1-
# Building Assets
1+
# Local Development
2+
Pterodactyl is now powered by Vuejs and Tailwindcss and uses webpack at its core to generate compiled assets. Release
3+
versions of Pterodactyl will include pre-compiled, minified, and hashed assets ready-to-go.
24

3-
```
5+
However, if you are interested in running custom themes or making modifications to the Vue files you'll need a build
6+
system in place to generate these compiled assets. To get your environment setup, you'll first need to install at least Nodejs
7+
`8`, and it is _highly_ recommended that you also install [Yarn](https://yarnpkg.com) to manage your `node_modules`.
8+
9+
### Install Dependencies
10+
```bash
411
yarn install
12+
```
13+
14+
The command above will download all of the dependencies necessary to get Pterodactyl assets building. After that, its as
15+
simple as running the command below to generate assets while you're developing.
16+
17+
```bash
18+
# build the compiled assets for development
19+
yarn run build
20+
21+
# build the assets automatically when files are modified
22+
yarn run watch
23+
```
24+
525

6-
php artisan vue-i18n:generate
7-
php artisan ziggy:generate resources/assets/scripts/helpers/ziggy.js
26+
### Hot Module Reloading
27+
For more advanced users, we also support 'Hot Module Reloading', allowing you to quickly see changes you're making
28+
to the Vue template files without having to reload the page you're on. To Get started with this, you just need
29+
to run the command below.
830

9-
npm run build
31+
```bash
32+
PUBLIC_PATH=http://192.168.1.1:8080 yarn run serve --host 192.168.1.1
1033
```
34+
35+
There are two _very important_ parts of this command to take note of and change for your specific environment. The first
36+
is the `--host` flag, which is required and should point to the machine where the `webpack-serve` server will be running.
37+
The second is the `PUBLIC_PATH` environment variable which is the URL pointing to the HMR server and is appended to all of
38+
the asset URLs used in Pterodactyl.
39+
40+
#### Vagrant
41+
If you want to use HMR with our Vagrant image, you can use `yarn run v:serve` as a shortcut for the correct parameters.
42+
In order to have proper file change detection you can use the [`vagrant-notify-forwarder`](https://github.com/mhallin/vagrant-notify-forwarder) to notify file events from the host to the VM.
43+
```sh
44+
vagrant plugin install vagrant-notify-forwarder
45+
vagrant reload
46+
```
47+
48+
### Building for Production
49+
Once you have your files squared away and ready for the live server, you'll be needing to generate compiled, minified, and
50+
hashed assets to push live. To do so, run the command below:
51+
52+
```bash
53+
yarn run build:production
54+
```
55+
56+
This will generate a production ready `bundle.js` and `bundle.css` as well as a `manifest.json` and store them in
57+
the `/public/assets` directory where they can then be access by clients, and read by the Panel.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Controllers\Api\Client;
4+
5+
use Illuminate\Http\Request;
6+
use Pterodactyl\Transformers\Api\Client\AccountTransformer;
7+
8+
class AccountController extends ClientApiController
9+
{
10+
public function index(Request $request): array
11+
{
12+
return $this->fractal->item($request->user())
13+
->transformWith($this->getTransformer(AccountTransformer::class))
14+
->toArray();
15+
}
16+
}

app/Http/Controllers/Auth/AbstractLoginController.php

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Illuminate\Contracts\Encryption\Encrypter;
1717
use Illuminate\Foundation\Auth\AuthenticatesUsers;
1818
use Pterodactyl\Traits\Helpers\ProvidesJWTServices;
19+
use Pterodactyl\Transformers\Api\Client\AccountTransformer;
1920
use Illuminate\Contracts\Cache\Repository as CacheRepository;
2021
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
2122

@@ -137,25 +138,35 @@ protected function sendLoginResponse(User $user, Request $request): JsonResponse
137138
$request->session()->regenerate();
138139
$this->clearLoginAttempts($request);
139140

140-
$token = $this->builder->setIssuer(config('app.url'))
141+
$this->auth->guard()->login($user, true);
142+
143+
return response()->json([
144+
'complete' => true,
145+
'intended' => $this->redirectPath(),
146+
'jwt' => $this->createJsonWebToken($user),
147+
]);
148+
}
149+
150+
/**
151+
* Create a new JWT for the request and sign it using the signing key.
152+
*
153+
* @param User $user
154+
* @return string
155+
*/
156+
protected function createJsonWebToken(User $user): string
157+
{
158+
$token = $this->builder
159+
->setIssuer('Pterodactyl Panel')
141160
->setAudience(config('app.url'))
142-
->setId(str_random(12), true)
161+
->setId(str_random(16), true)
143162
->setIssuedAt(Chronos::now()->getTimestamp())
144163
->setNotBefore(Chronos::now()->getTimestamp())
145164
->setExpiration(Chronos::now()->addSeconds(config('session.lifetime'))->getTimestamp())
146-
->set('user', $user->only([
147-
'id', 'uuid', 'username', 'email', 'name_first', 'name_last', 'language', 'root_admin',
148-
]))
165+
->set('user', (new AccountTransformer())->transform($user))
149166
->sign($this->getJWTSigner(), $this->getJWTSigningKey())
150167
->getToken();
151168

152-
$this->auth->guard()->login($user, true);
153-
154-
return response()->json([
155-
'complete' => true,
156-
'intended' => $this->redirectPath(),
157-
'token' => $token->__toString(),
158-
]);
169+
return $token->__toString();
159170
}
160171

161172
/**

app/Http/Kernel.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Pterodactyl\Http;
44

5-
use Pterodactyl\Http\Middleware\MaintenanceMiddleware;
65
use Pterodactyl\Models\ApiKey;
76
use Illuminate\Auth\Middleware\Authorize;
87
use Illuminate\Auth\Middleware\Authenticate;
@@ -21,6 +20,7 @@
2120
use Pterodactyl\Http\Middleware\AccessingValidServer;
2221
use Pterodactyl\Http\Middleware\Api\SetSessionDriver;
2322
use Illuminate\View\Middleware\ShareErrorsFromSession;
23+
use Pterodactyl\Http\Middleware\MaintenanceMiddleware;
2424
use Pterodactyl\Http\Middleware\RedirectIfAuthenticated;
2525
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
2626
use Pterodactyl\Http\Middleware\Api\AuthenticateIPAccess;
@@ -71,15 +71,15 @@ class Kernel extends HttpKernel
7171
RequireTwoFactorAuthentication::class,
7272
],
7373
'api' => [
74-
'throttle:120,1',
74+
'throttle:240,1',
7575
ApiSubstituteBindings::class,
7676
SetSessionDriver::class,
7777
'api..key:' . ApiKey::TYPE_APPLICATION,
7878
AuthenticateApplicationUser::class,
7979
AuthenticateIPAccess::class,
8080
],
8181
'client-api' => [
82-
'throttle:60,1',
82+
'throttle:240,1',
8383
SubstituteClientApiBindings::class,
8484
SetSessionDriver::class,
8585
'api..key:' . ApiKey::TYPE_ACCOUNT,

app/Http/Middleware/Api/AuthenticateKey.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,16 @@ protected function authenticateJWT(string $token): ApiKey
9797
throw new HttpException(401, null, null, ['WWW-Authenticate' => 'Bearer']);
9898
}
9999

100+
// Run through the token validation and throw an exception if the token is not valid.
101+
if (
102+
$token->getClaim('nbf') > Chronos::now()->getTimestamp()
103+
|| $token->getClaim('iss') !== 'Pterodactyl Panel'
104+
|| $token->getClaim('aud') !== config('app.url')
105+
|| $token->getClaim('exp') <= Chronos::now()->getTimestamp()
106+
) {
107+
throw new AccessDeniedHttpException;
108+
}
109+
100110
return (new ApiKey)->forceFill([
101111
'user_id' => object_get($token->getClaim('user'), 'id', 0),
102112
'key_type' => ApiKey::TYPE_ACCOUNT,

app/Services/Helpers/AssetHashService.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,25 @@ public function __construct(Application $application, CacheRepository $cache, Fi
5858
public function url(string $resource): string
5959
{
6060
$file = last(explode('/', $resource));
61+
$data = array_get($this->manifest(), $file, $file);
6162

62-
return '/' . ltrim(str_replace($file, array_get($this->manifest(), $file, $file), $resource), '/');
63+
return str_replace($file, array_get($data, 'src', $file), $resource);
64+
}
65+
66+
/**
67+
* Return the data integrity hash for a resource.
68+
*
69+
* @param string $resource
70+
* @return string
71+
*
72+
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
73+
*/
74+
public function integrity(string $resource): string
75+
{
76+
$file = last(explode('/', $resource));
77+
$data = array_get($this->manifest(), $file, $file);
78+
79+
return array_get($data, 'integrity', '');
6380
}
6481

6582
/**
@@ -72,7 +89,11 @@ public function url(string $resource): string
7289
*/
7390
public function css(string $resource): string
7491
{
75-
return '<link href="' . $this->url($resource) . '" rel="stylesheet preload" crossorigin="anonymous" referrerpolicy="no-referrer">';
92+
return '<link href="' . $this->url($resource) . '"
93+
rel="stylesheet preload"
94+
crossorigin="anonymous"
95+
integrity="' . $this->integrity($resource) . '"
96+
referrerpolicy="no-referrer">';
7697
}
7798

7899
/**
@@ -85,7 +106,9 @@ public function css(string $resource): string
85106
*/
86107
public function js(string $resource): string
87108
{
88-
return '<script src="' . $this->url($resource) . '" crossorigin="anonymous"></script>';
109+
return '<script src="' . $this->url($resource) . '"
110+
integrity="' . $this->integrity($resource) . '"
111+
crossorigin="anonymous"></script>';
89112
}
90113

91114
/**
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Pterodactyl\Transformers\Api\Client;
4+
5+
use Pterodactyl\Models\User;
6+
7+
class AccountTransformer extends BaseClientTransformer
8+
{
9+
/**
10+
* Return the resource name for the JSONAPI output.
11+
*
12+
* @return string
13+
*/
14+
public function getResourceName(): string
15+
{
16+
return 'user';
17+
}
18+
19+
/**
20+
* Return basic information about the currently logged in user.
21+
*
22+
* @param \Pterodactyl\Models\User $model
23+
* @return array
24+
*/
25+
public function transform(User $model)
26+
{
27+
return [
28+
'id' => $model->id,
29+
'admin' => $model->root_admin,
30+
'username' => $model->username,
31+
'email' => $model->email,
32+
'first_name' => $model->name_first,
33+
'last_name' => $model->name_last,
34+
'language' => $model->language,
35+
];
36+
}
37+
}

0 commit comments

Comments
 (0)