From 969b16a56321cded9f770fac5edd692bd11d6c8d Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 2 Jun 2018 21:32:26 +0000 Subject: [PATCH 01/62] Apply fixes from StyleCI [ci skip] [skip ci] --- .../Repository/RepositoryInterface.php | 2 +- .../Repository/ServerRepositoryInterface.php | 2 +- .../Admin/StatisticsController.php | 22 +++++++--------- app/Http/Kernel.php | 2 +- .../Eloquent/EloquentRepository.php | 2 +- .../Eloquent/ServerRepository.php | 2 +- .../Controllers/PlainJavascriptInjection.php | 8 +++--- ..._05_04_123826_add_maintenance_to_nodes.php | 4 +-- .../Admin/StatisticsControllerTest.php | 25 ++++++++----------- 9 files changed, 30 insertions(+), 39 deletions(-) diff --git a/app/Contracts/Repository/RepositoryInterface.php b/app/Contracts/Repository/RepositoryInterface.php index 1a26eed7e..4cdebf7bb 100644 --- a/app/Contracts/Repository/RepositoryInterface.php +++ b/app/Contracts/Repository/RepositoryInterface.php @@ -202,7 +202,7 @@ interface RepositoryInterface public function insertIgnore(array $values): bool; /** - * Get the amount of entries in the database + * Get the amount of entries in the database. * * @return int */ diff --git a/app/Contracts/Repository/ServerRepositoryInterface.php b/app/Contracts/Repository/ServerRepositoryInterface.php index 344fa248c..6f392d05d 100644 --- a/app/Contracts/Repository/ServerRepositoryInterface.php +++ b/app/Contracts/Repository/ServerRepositoryInterface.php @@ -147,7 +147,7 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter public function isUniqueUuidCombo(string $uuid, string $short): bool; /** - * Get the amount of servers that are suspended + * Get the amount of servers that are suspended. * * @return int */ diff --git a/app/Http/Controllers/Admin/StatisticsController.php b/app/Http/Controllers/Admin/StatisticsController.php index 2327fd88d..1ae807565 100644 --- a/app/Http/Controllers/Admin/StatisticsController.php +++ b/app/Http/Controllers/Admin/StatisticsController.php @@ -2,16 +2,14 @@ namespace Pterodactyl\Http\Controllers\Admin; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\DB; -use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; -use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; -use Pterodactyl\Contracts\Repository\EggRepositoryInterface; -use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; -use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; -use Pterodactyl\Contracts\Repository\UserRepositoryInterface; use Pterodactyl\Http\Controllers\Controller; +use Pterodactyl\Contracts\Repository\EggRepositoryInterface; use Pterodactyl\Traits\Controllers\PlainJavascriptInjection; +use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; +use Pterodactyl\Contracts\Repository\UserRepositoryInterface; +use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; +use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; +use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; class StatisticsController extends Controller { @@ -29,15 +27,14 @@ class StatisticsController extends Controller private $userRepository; - function __construct( + public function __construct( AllocationRepositoryInterface $allocationRepository, DatabaseRepositoryInterface $databaseRepository, EggRepositoryInterface $eggRepository, NodeRepositoryInterface $nodeRepository, ServerRepositoryInterface $serverRepository, UserRepositoryInterface $userRepository - ) - { + ) { $this->allocationRepository = $allocationRepository; $this->databaseRepository = $databaseRepository; $this->eggRepository = $eggRepository; @@ -83,7 +80,7 @@ class StatisticsController extends Controller 'nodes' => $nodes, 'tokens' => $tokens, ]); - + return view('admin.statistics', [ 'servers' => $servers, 'nodes' => $nodes, @@ -97,5 +94,4 @@ class StatisticsController extends Controller 'totalAllocations' => $totalAllocations, ]); } - } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index d21c8d3c8..404c40ae9 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -2,7 +2,6 @@ namespace Pterodactyl\Http; -use Pterodactyl\Http\Middleware\MaintenanceMiddleware; use Pterodactyl\Models\ApiKey; use Illuminate\Auth\Middleware\Authorize; use Illuminate\Auth\Middleware\Authenticate; @@ -21,6 +20,7 @@ use Illuminate\Routing\Middleware\SubstituteBindings; use Pterodactyl\Http\Middleware\AccessingValidServer; use Pterodactyl\Http\Middleware\Api\SetSessionDriver; use Illuminate\View\Middleware\ShareErrorsFromSession; +use Pterodactyl\Http\Middleware\MaintenanceMiddleware; use Pterodactyl\Http\Middleware\RedirectIfAuthenticated; use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth; use Pterodactyl\Http\Middleware\Api\AuthenticateIPAccess; diff --git a/app/Repositories/Eloquent/EloquentRepository.php b/app/Repositories/Eloquent/EloquentRepository.php index 64e7cfb60..cf0931799 100644 --- a/app/Repositories/Eloquent/EloquentRepository.php +++ b/app/Repositories/Eloquent/EloquentRepository.php @@ -298,7 +298,7 @@ abstract class EloquentRepository extends Repository implements RepositoryInterf } /** - * Get the amount of entries in the database + * Get the amount of entries in the database. * * @return int */ diff --git a/app/Repositories/Eloquent/ServerRepository.php b/app/Repositories/Eloquent/ServerRepository.php index f448f0b78..e900c92dd 100644 --- a/app/Repositories/Eloquent/ServerRepository.php +++ b/app/Repositories/Eloquent/ServerRepository.php @@ -330,7 +330,7 @@ class ServerRepository extends EloquentRepository implements ServerRepositoryInt } /** - * Get the amount of servers that are suspended + * Get the amount of servers that are suspended. * * @return int */ diff --git a/app/Traits/Controllers/PlainJavascriptInjection.php b/app/Traits/Controllers/PlainJavascriptInjection.php index eae53bfbc..f514eb1af 100644 --- a/app/Traits/Controllers/PlainJavascriptInjection.php +++ b/app/Traits/Controllers/PlainJavascriptInjection.php @@ -3,7 +3,7 @@ * Created by PhpStorm. * User: Stan * Date: 26-5-2018 - * Time: 20:56 + * Time: 20:56. */ namespace Pterodactyl\Traits\Controllers; @@ -12,13 +12,11 @@ use JavaScript; trait PlainJavascriptInjection { - /** - * Injects statistics into javascript + * Injects statistics into javascript. */ public function injectJavascript($data) { Javascript::put($data); } - -} \ No newline at end of file +} diff --git a/database/migrations/2018_05_04_123826_add_maintenance_to_nodes.php b/database/migrations/2018_05_04_123826_add_maintenance_to_nodes.php index 799f1df23..04fdf000f 100644 --- a/database/migrations/2018_05_04_123826_add_maintenance_to_nodes.php +++ b/database/migrations/2018_05_04_123826_add_maintenance_to_nodes.php @@ -14,7 +14,7 @@ class AddMaintenanceToNodes extends Migration public function up() { Schema::table('nodes', function (Blueprint $table) { - $table->boolean('maintenance_mode')->after('behind_proxy')->default(false); + $table->boolean('maintenance_mode')->after('behind_proxy')->default(false); }); } @@ -26,7 +26,7 @@ class AddMaintenanceToNodes extends Migration public function down() { Schema::table('nodes', function (Blueprint $table) { - $table->dropColumn('maintenance_mode'); + $table->dropColumn('maintenance_mode'); }); } } diff --git a/tests/Unit/Http/Controllers/Admin/StatisticsControllerTest.php b/tests/Unit/Http/Controllers/Admin/StatisticsControllerTest.php index f3a20f8ac..fe41932bd 100644 --- a/tests/Unit/Http/Controllers/Admin/StatisticsControllerTest.php +++ b/tests/Unit/Http/Controllers/Admin/StatisticsControllerTest.php @@ -3,24 +3,22 @@ * Created by PhpStorm. * User: Stan * Date: 26-5-2018 - * Time: 21:06 + * Time: 21:06. */ namespace Tests\Unit\Http\Controllers\Admin; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Routing\Controller; use Mockery as m; -use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; -use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; -use Pterodactyl\Contracts\Repository\EggRepositoryInterface; -use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; -use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; -use Pterodactyl\Contracts\Repository\UserRepositoryInterface; -use Pterodactyl\Http\Controllers\Admin\StatisticsController; use Pterodactyl\Models\Node; use Tests\Assertions\ControllerAssertionsTrait; use Tests\Unit\Http\Controllers\ControllerTestCase; +use Pterodactyl\Contracts\Repository\EggRepositoryInterface; +use Pterodactyl\Http\Controllers\Admin\StatisticsController; +use Pterodactyl\Contracts\Repository\NodeRepositoryInterface; +use Pterodactyl\Contracts\Repository\UserRepositoryInterface; +use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; +use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; +use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; class StatisticsControllerTest extends ControllerTestCase { @@ -88,7 +86,7 @@ class StatisticsControllerTest extends ControllerTestCase 'disk' => [ 'value' => 1024, 'max' => 512, - ] + ], ]); $controller->shouldReceive('injectJavascript')->once(); @@ -106,8 +104,7 @@ class StatisticsControllerTest extends ControllerTestCase $this->eggRepository, $this->nodeRepository, $this->serverRepository, - $this->userRepository] + $this->userRepository, ] ); } - -} \ No newline at end of file +} From d73e5a2274a3bdf44821451c3ac51f1ab139da95 Mon Sep 17 00:00:00 2001 From: Jacob Gee-Clarke Date: Sat, 2 Jun 2018 22:34:01 +0100 Subject: [PATCH 02/62] Fixed my fix to fix the 500 error on /api/application/nodes when not specifying a daemon_base (#1182) --- app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php b/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php index 20a29f199..0f39fd2f8 100644 --- a/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php +++ b/app/Http/Requests/Api/Application/Nodes/StoreNodeRequest.php @@ -74,7 +74,7 @@ class StoreNodeRequest extends ApplicationApiRequest $response = parent::validated(); $response['daemonListen'] = $response['daemon_listen']; $response['daemonSFTP'] = $response['daemon_sftp']; - $response['daemonBase'] = $response['daemon_base']; + $response['daemonBase'] = $response['daemon_base'] ?? (new Node)->getAttribute('daemonBase'); unset($response['daemon_base'], $response['daemon_listen'], $response['daemon_sftp']); From 8f0c740a15e8b338c97b47277cdc9c71ca88a753 Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Sun, 3 Jun 2018 23:36:35 -0400 Subject: [PATCH 03/62] Update issue templates (#1188) * Update issue templates * Delete ISSUE_TEMPLATE.md --- .github/ISSUE_TEMPLATE.md | 26 ------------------ .github/ISSUE_TEMPLATE/---bug-report.md | 27 +++++++++++++++++++ .github/ISSUE_TEMPLATE/---feature-request.md | 17 ++++++++++++ .github/ISSUE_TEMPLATE/--installation-help.md | 8 ++++++ .github/ISSUE_TEMPLATE/bug-report.md | 27 +++++++++++++++++++ .github/ISSUE_TEMPLATE/feature-request.md | 17 ++++++++++++ 6 files changed, 96 insertions(+), 26 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/ISSUE_TEMPLATE/---bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/---feature-request.md create mode 100644 .github/ISSUE_TEMPLATE/--installation-help.md create mode 100644 .github/ISSUE_TEMPLATE/bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/feature-request.md diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 9b959e58f..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,26 +0,0 @@ - - - -* Panel or Daemon: -* Version of Panel/Daemon: -* Server's OS: -* Your Computer's OS & Browser: - ------------------------- - - diff --git a/.github/ISSUE_TEMPLATE/---bug-report.md b/.github/ISSUE_TEMPLATE/---bug-report.md new file mode 100644 index 000000000..6d69080b1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---bug-report.md @@ -0,0 +1,27 @@ +--- +name: "\U0001F41B Bug Report" +about: Create a report to help us resolve a bug or error + +--- + +**Background (please complete the following information):** +* Panel or Daemon: +* Version of Panel/Daemon: +* Server's OS: +* Your Computer's OS & Browser: + +**Describe the bug** +A clear and concise description of what the bug is. +Please provide additional information too, depending on what you have issues with: +Panel: `php -v` (the php version in use). +Daemon: `uname -a` and `docker info` (your kernel version and information regarding docker) + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. If applicable, add screenshots or a recording to help explain your problem. diff --git a/.github/ISSUE_TEMPLATE/---feature-request.md b/.github/ISSUE_TEMPLATE/---feature-request.md new file mode 100644 index 000000000..64fa679ba --- /dev/null +++ b/.github/ISSUE_TEMPLATE/---feature-request.md @@ -0,0 +1,17 @@ +--- +name: "\U0001F680 Feature Request" +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/--installation-help.md b/.github/ISSUE_TEMPLATE/--installation-help.md new file mode 100644 index 000000000..fa10ca975 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/--installation-help.md @@ -0,0 +1,8 @@ +--- +name: "⛔ Installation Help" +about: 'Visit our Discord for installation help: https://pterodactyl.io/discord' + +--- + +We use GitHub issues only to discuss about Pterodactyl bugs and new features. For +this kind of questions about using Pterodactyl, please visit our Discord for assistance: https://pterodactyl.io/discord diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md new file mode 100644 index 000000000..5cb3eaef7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -0,0 +1,27 @@ +--- +name: Bug Report +about: Create a report to help us resolve a bug or error + +--- + +**Background (please complete the following information):** +* Panel or Daemon: +* Version of Panel/Daemon: +* Server's OS: +* Your Computer's OS & Browser: + +**Describe the bug** +A clear and concise description of what the bug is. +Please provide additional information too, depending on what you have issues with: +Panel: `php -v` (the php version in use). +Daemon: `uname -a` and `docker info` (your kernel version and information regarding docker) + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. If applicable, add screenshots or a recording to help explain your problem. diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md new file mode 100644 index 000000000..817c80c1f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.md @@ -0,0 +1,17 @@ +--- +name: Feature Request +about: Suggest an idea for this project + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From f54dc24cf440c769c1b913e4d360960644179367 Mon Sep 17 00:00:00 2001 From: Lance Pioch Date: Sun, 3 Jun 2018 23:40:38 -0400 Subject: [PATCH 04/62] Remove dupe issues thanks Microsoft (#1189) * Delete bug-report.md * Delete feature-request.md --- .github/ISSUE_TEMPLATE/bug-report.md | 27 ----------------------- .github/ISSUE_TEMPLATE/feature-request.md | 17 -------------- 2 files changed, 44 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug-report.md delete mode 100644 .github/ISSUE_TEMPLATE/feature-request.md diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md deleted file mode 100644 index 5cb3eaef7..000000000 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -name: Bug Report -about: Create a report to help us resolve a bug or error - ---- - -**Background (please complete the following information):** -* Panel or Daemon: -* Version of Panel/Daemon: -* Server's OS: -* Your Computer's OS & Browser: - -**Describe the bug** -A clear and concise description of what the bug is. -Please provide additional information too, depending on what you have issues with: -Panel: `php -v` (the php version in use). -Daemon: `uname -a` and `docker info` (your kernel version and information regarding docker) - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. If applicable, add screenshots or a recording to help explain your problem. diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/.github/ISSUE_TEMPLATE/feature-request.md deleted file mode 100644 index 817c80c1f..000000000 --- a/.github/ISSUE_TEMPLATE/feature-request.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Feature Request -about: Suggest an idea for this project - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. From 5f90d841d063852b7e3692359a35deb8f5258e51 Mon Sep 17 00:00:00 2001 From: Jayden Downes <35357527+JaydenDownes@users.noreply.github.com> Date: Tue, 5 Jun 2018 10:33:34 +0800 Subject: [PATCH 05/62] Fixed Search Bar Scaling in Firefox (#1187) Fixed scaling issue with Firefox where it would scale the search bar to 30% of the width of the box-tools container instead of 30% of the row container. (Note this is not a fix for the issue with it appearing on a separate line on mobiles). --- public/themes/pterodactyl/css/pterodactyl.css | 5 +++++ resources/themes/pterodactyl/base/index.blade.php | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/public/themes/pterodactyl/css/pterodactyl.css b/public/themes/pterodactyl/css/pterodactyl.css index 41f163f3b..a4e4c4cf7 100644 --- a/public/themes/pterodactyl/css/pterodactyl.css +++ b/public/themes/pterodactyl/css/pterodactyl.css @@ -474,6 +474,11 @@ label.control-label > span.field-optional:before { width: auto; } +.search01 { + width: 30%; +} + .number-info-box-content { padding: 15px 10px 0; } + diff --git a/resources/themes/pterodactyl/base/index.blade.php b/resources/themes/pterodactyl/base/index.blade.php index 28f4c4d57..1fd44caa7 100644 --- a/resources/themes/pterodactyl/base/index.blade.php +++ b/resources/themes/pterodactyl/base/index.blade.php @@ -23,10 +23,10 @@

@lang('base.index.list')

-
+
- +
From e5e66fdb583f583839e23453a21a315336734d05 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Mon, 11 Jun 2018 20:42:01 -0700 Subject: [PATCH 06/62] Fix error handling in dashboard --- resources/assets/scripts/components/dashboard/Dashboard.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/assets/scripts/components/dashboard/Dashboard.vue b/resources/assets/scripts/components/dashboard/Dashboard.vue index ca3a5555a..575b77006 100644 --- a/resources/assets/scripts/components/dashboard/Dashboard.vue +++ b/resources/assets/scripts/components/dashboard/Dashboard.vue @@ -98,7 +98,7 @@ console.error(err); const response = err.response; if (response.data && _.isObject(response.data.errors)) { - response.data.errors.forEach(function (error) { + response.data.errors.forEach(error => { this.error(error.detail); }); } From 14927c3e7ebff2d2935f50b1a70625520706e9a1 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Mon, 11 Jun 2018 22:36:43 -0700 Subject: [PATCH 07/62] Add base UI for account management --- package.json | 2 +- .../scripts/components/dashboard/Account.vue | 50 +++++++++-- .../dashboard/account/UpdateEmail.vue | 88 +++++++++++++++++++ .../assets/scripts/store/modules/auth.js | 50 ++++++++++- .../assets/styles/components/buttons.css | 12 +++ resources/assets/styles/components/forms.css | 21 +++++ routes/api-client.php | 1 + routes/base.php | 10 +-- 8 files changed, 220 insertions(+), 14 deletions(-) create mode 100644 resources/assets/scripts/components/dashboard/account/UpdateEmail.vue diff --git a/package.json b/package.json index 45f995c34..a11bf7ee6 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "watch": "NODE_ENV=development ./node_modules/.bin/webpack --watch --progress", "build": "NODE_ENV=development ./node_modules/.bin/webpack --progress", "build:production": "NODE_ENV=production ./node_modules/.bin/webpack", - "serve": "webpack-serve --hot --config ./webpack.config.js", + "serve": "NODE_ENV=development webpack-serve --hot --config ./webpack.config.js", "v:serve": "PUBLIC_PATH=http://192.168.50.2:8080 NODE_ENV=development webpack-serve --hot --config ./webpack.config.js --host 192.168.50.2 --no-clipboard" } } diff --git a/resources/assets/scripts/components/dashboard/Account.vue b/resources/assets/scripts/components/dashboard/Account.vue index 281ce77b9..655acfb63 100644 --- a/resources/assets/scripts/components/dashboard/Account.vue +++ b/resources/assets/scripts/components/dashboard/Account.vue @@ -1,13 +1,51 @@ - - diff --git a/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue b/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue new file mode 100644 index 000000000..5f06ac77c --- /dev/null +++ b/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/resources/assets/scripts/store/modules/auth.js b/resources/assets/scripts/store/modules/auth.js index 7ccd43721..6999f652f 100644 --- a/resources/assets/scripts/store/modules/auth.js +++ b/resources/assets/scripts/store/modules/auth.js @@ -13,12 +13,20 @@ export default { * @param state * @returns {User|null} */ - currentUser: function (state) { + getUser: function (state) { return state.user; - } + }, }, setters: {}, actions: { + /** + * Log a user into the Panel. + * + * @param commit + * @param {String} user + * @param {String} password + * @returns {Promise} + */ login: ({commit}, {user, password}) => { return new Promise((resolve, reject) => { window.axios.post(route('auth.login'), {user, password}) @@ -47,6 +55,13 @@ export default { .catch(reject); }); }, + + /** + * Log a user out of the Panel. + * + * @param commit + * @returns {Promise} + */ logout: function ({commit}) { return new Promise((resolve, reject) => { window.axios.get(route('auth.logout')) @@ -57,8 +72,39 @@ export default { .catch(reject); }) }, + + /** + * Update a user's email address on the Panel and store the updated result in Vuex. + * + * @param commit + * @param {String} email + * @param {String} password + * @param {String} confirm + * @return {Promise} + */ + updateEmail: function ({commit}, {email, password, confirm}) { + return new Promise((resolve, reject) => { + window.axios.put(route('api.client.account.update-email'), { + email, password, password_confirmation: confirm + }) + .then(response => { + // If there is a 302 redirect or some other odd behavior (basically, response that isnt + // in JSON format) throw an error and don't try to continue with the login. + if (!(response.data instanceof Object)) { + return reject(new Error('An error was encountered while processing this request.')); + } + + commit('setEmail', response.data.email); + return resolve(); + }) + .catch(reject); + }); + }, }, mutations: { + setEmail: function (state, email) { + state.user.email = email; + }, login: function (state, {jwt}) { localStorage.setItem('token', jwt); state.user = User.fromToken(jwt); diff --git a/resources/assets/styles/components/buttons.css b/resources/assets/styles/components/buttons.css index d2721777f..bc14f09d4 100644 --- a/resources/assets/styles/components/buttons.css +++ b/resources/assets/styles/components/buttons.css @@ -12,6 +12,14 @@ } } + &.btn-secondary { + @apply .border .border-grey-light .text-grey-dark; + + &:hover:enabled { + @apply .border-grey .text-grey-darker; + } + } + /** * Button Sizes */ @@ -19,6 +27,10 @@ @apply .p-4 .w-full .uppercase .tracking-wide .text-sm; } + &.btn-sm { + @apply .px-6 .py-3 .uppercase .tracking-wide .text-sm; + } + &:disabled, &.disabled { opacity: 0.55; cursor: default; diff --git a/resources/assets/styles/components/forms.css b/resources/assets/styles/components/forms.css index f9de27916..9d87c79a7 100644 --- a/resources/assets/styles/components/forms.css +++ b/resources/assets/styles/components/forms.css @@ -30,3 +30,24 @@ top: 14px; transition: transform 200ms ease-out; } + +.input { + @apply .appearance-none .p-3 .rounded .border .text-grey-darker .w-full; + transition: all 100ms linear; + + &:focus { + @apply .border-blue-light; + } + + &:required, &:invalid { + box-shadow: none; + } +} + +.input-label { + @apply .block .uppercase .tracking-wide .text-grey-darkest .text-xs .font-bold .mb-1; +} + +.input-help { + @apply .text-xs .text-grey .pt-2; +} diff --git a/routes/api-client.php b/routes/api-client.php index 72be367f7..afee2defd 100644 --- a/routes/api-client.php +++ b/routes/api-client.php @@ -14,6 +14,7 @@ Route::get('/', 'ClientController@index')->name('api.client.index'); Route::group(['prefix' => '/account'], function () { Route::get('/', 'AccountController@index')->name('api.client.account'); + Route::put('/email', 'AccountController@updateEmail')->name('api.client.account.update-email'); }); /* diff --git a/routes/base.php b/routes/base.php index 4d86bada9..4c8faa333 100644 --- a/routes/base.php +++ b/routes/base.php @@ -16,11 +16,11 @@ Route::get('/', 'IndexController@index')->name('index'); | Endpoint: /account | */ -Route::group(['prefix' => 'account'], function () { - Route::get('/', 'AccountController@index')->name('account'); - - Route::post('/', 'AccountController@update'); -}); +//Route::group(['prefix' => 'account'], function () { +// Route::get('/', 'AccountController@index')->name('account'); +// +// Route::post('/', 'AccountController@update'); +//}); /* |-------------------------------------------------------------------------- From b8b9acd0e695fea143815fe42a61f297e94c5310 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Mon, 11 Jun 2018 22:56:57 -0700 Subject: [PATCH 08/62] Get the base email update working through the API. Still going to need to determine the best course of action to update the token on the client side. --- .../Api/Client/AccountController.php | 43 +++++++++++++++++++ .../Api/Client/Account/UpdateEmailRequest.php | 42 ++++++++++++++++++ .../dashboard/account/UpdateEmail.vue | 2 +- routes/api-client.php | 1 + 4 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 app/Http/Requests/Api/Client/Account/UpdateEmailRequest.php diff --git a/app/Http/Controllers/Api/Client/AccountController.php b/app/Http/Controllers/Api/Client/AccountController.php index e683d3a0b..fc0f22ecd 100644 --- a/app/Http/Controllers/Api/Client/AccountController.php +++ b/app/Http/Controllers/Api/Client/AccountController.php @@ -3,14 +3,57 @@ namespace Pterodactyl\Http\Controllers\Api\Client; use Illuminate\Http\Request; +use Pterodactyl\Services\Users\UserUpdateService; use Pterodactyl\Transformers\Api\Client\AccountTransformer; +use Pterodactyl\Http\Requests\Api\Client\Account\UpdateEmailRequest; class AccountController extends ClientApiController { + /** + * @var \Pterodactyl\Services\Users\UserUpdateService + */ + private $updateService; + + /** + * AccountController constructor. + * + * @param \Pterodactyl\Services\Users\UserUpdateService $updateService + */ + public function __construct(UserUpdateService $updateService) + { + parent::__construct(); + + $this->updateService = $updateService; + } + + /** + * @param Request $request + * @return array + */ public function index(Request $request): array { return $this->fractal->item($request->user()) ->transformWith($this->getTransformer(AccountTransformer::class)) ->toArray(); } + + /** + * Update the authenticated user's email address if their password matches. + * + * @param UpdateEmailRequest $request + * @return array + * + * @throws \Pterodactyl\Exceptions\Model\DataValidationException + * @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException + */ + public function updateEmail(UpdateEmailRequest $request): array + { + $updated = $this->updateService->handle($request->user(), [ + 'email' => $request->input('email'), + ]); + + return $this->fractal->item($updated->get('model')) + ->transformWith($this->getTransformer(AccountTransformer::class)) + ->toArray(); + } } diff --git a/app/Http/Requests/Api/Client/Account/UpdateEmailRequest.php b/app/Http/Requests/Api/Client/Account/UpdateEmailRequest.php new file mode 100644 index 000000000..f354d120a --- /dev/null +++ b/app/Http/Requests/Api/Client/Account/UpdateEmailRequest.php @@ -0,0 +1,42 @@ +input('password'), $this->user()->password)) { + throw new InvalidPasswordProvidedException(trans('base.account.invalid_password')); + } + + return true; + } + + /** + * @return array + */ + public function rules(): array + { + $rules = User::getUpdateRulesForId($this->user()->id); + + return [ + 'email' => $rules['email'], + 'password' => array_merge($rules['password'], ['confirmed']), + ]; + } +} diff --git a/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue b/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue index 5f06ac77c..0e4d82b69 100644 --- a/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue +++ b/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue @@ -64,7 +64,7 @@ }) .catch(error => { if (!error.response) { - return console.error(error); + this.error(error.message); } const response = error.response; diff --git a/routes/api-client.php b/routes/api-client.php index afee2defd..77aeac295 100644 --- a/routes/api-client.php +++ b/routes/api-client.php @@ -14,6 +14,7 @@ Route::get('/', 'ClientController@index')->name('api.client.index'); Route::group(['prefix' => '/account'], function () { Route::get('/', 'AccountController@index')->name('api.client.account'); + Route::put('/email', 'AccountController@updateEmail')->name('api.client.account.update-email'); }); From 24bb8da43dcc3bf7f01628d84361d6cff6becd5e Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 16 Jun 2018 12:43:32 -0700 Subject: [PATCH 09/62] Fix CSS issue with login page due to input classes --- app/Services/Helpers/AssetHashService.php | 1 + package.json | 2 +- resources/assets/scripts/app.js | 5 ++--- .../assets/scripts/components/auth/ForgotPassword.vue | 2 +- resources/assets/scripts/components/auth/LoginForm.vue | 4 ++-- .../assets/scripts/components/auth/ResetPassword.vue | 6 +++--- .../assets/scripts/components/auth/TwoFactorForm.vue | 2 +- resources/assets/scripts/store/index.js | 8 ++++++-- resources/assets/styles/components/forms.css | 2 +- 9 files changed, 18 insertions(+), 14 deletions(-) diff --git a/app/Services/Helpers/AssetHashService.php b/app/Services/Helpers/AssetHashService.php index 771516c29..33945578c 100644 --- a/app/Services/Helpers/AssetHashService.php +++ b/app/Services/Helpers/AssetHashService.php @@ -91,6 +91,7 @@ class AssetHashService { return ''; diff --git a/package.json b/package.json index a11bf7ee6..c918bc618 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "watch": "NODE_ENV=development ./node_modules/.bin/webpack --watch --progress", "build": "NODE_ENV=development ./node_modules/.bin/webpack --progress", "build:production": "NODE_ENV=production ./node_modules/.bin/webpack", - "serve": "NODE_ENV=development webpack-serve --hot --config ./webpack.config.js", + "serve": "NODE_ENV=development webpack-serve --hot --config ./webpack.config.js --no-clipboard", "v:serve": "PUBLIC_PATH=http://192.168.50.2:8080 NODE_ENV=development webpack-serve --hot --config ./webpack.config.js --host 192.168.50.2 --no-clipboard" } } diff --git a/resources/assets/scripts/app.js b/resources/assets/scripts/app.js index 704f3d4ef..fe58baf9f 100644 --- a/resources/assets/scripts/app.js +++ b/resources/assets/scripts/app.js @@ -3,6 +3,7 @@ import Vuex from 'vuex'; import vuexI18n from 'vuex-i18n'; import VueRouter from 'vue-router'; +Vue.config.productionTip = false; require('./bootstrap'); // Helpers @@ -10,15 +11,13 @@ import { Ziggy } from './helpers/ziggy'; import Locales from './../../../resources/lang/locales'; import { flash } from './mixins/flash'; import { routes } from './routes'; -import storeData from './store/index.js'; +import store from './store/index.js'; window.events = new Vue; window.Ziggy = Ziggy; -Vue.config.productionTip = false; Vue.use(Vuex); -const store = new Vuex.Store(storeData); const route = require('./../../../vendor/tightenco/ziggy/src/js/route').default; Vue.mixin({ methods: { route } }); diff --git a/resources/assets/scripts/components/auth/ForgotPassword.vue b/resources/assets/scripts/components/auth/ForgotPassword.vue index 5a5dc42b8..ce43609da 100644 --- a/resources/assets/scripts/components/auth/ForgotPassword.vue +++ b/resources/assets/scripts/components/auth/ForgotPassword.vue @@ -5,7 +5,7 @@ >
-
-
-
-
-
-
- Date: Sat, 16 Jun 2018 14:05:39 -0700 Subject: [PATCH 10/62] Change login handling to automatically redirect a user if their session will need renewal. --- .../Auth/AbstractLoginController.php | 8 +- app/Http/Middleware/Api/AuthenticateKey.php | 10 ++- config/jwt.php | 1 + resources/assets/scripts/app.js | 11 +-- resources/assets/scripts/models/user.js | 22 +++-- resources/assets/scripts/router.js | 81 +++++++++++++++++++ resources/assets/scripts/store/index.js | 14 +++- routes/auth.php | 2 +- 8 files changed, 126 insertions(+), 23 deletions(-) create mode 100644 resources/assets/scripts/router.js diff --git a/app/Http/Controllers/Auth/AbstractLoginController.php b/app/Http/Controllers/Auth/AbstractLoginController.php index de8e275d3..02f425216 100644 --- a/app/Http/Controllers/Auth/AbstractLoginController.php +++ b/app/Http/Controllers/Auth/AbstractLoginController.php @@ -155,13 +155,15 @@ abstract class AbstractLoginController extends Controller */ protected function createJsonWebToken(User $user): string { + $now = Chronos::now('utc'); + $token = $this->builder ->setIssuer('Pterodactyl Panel') ->setAudience(config('app.url')) ->setId(str_random(16), true) - ->setIssuedAt(Chronos::now()->getTimestamp()) - ->setNotBefore(Chronos::now()->getTimestamp()) - ->setExpiration(Chronos::now()->addSeconds(config('session.lifetime'))->getTimestamp()) + ->setIssuedAt($now->getTimestamp()) + ->setNotBefore($now->getTimestamp()) + ->setExpiration($now->addSeconds(config('jwt.lifetime'))->getTimestamp()) ->set('user', (new AccountTransformer())->transform($user)) ->sign($this->getJWTSigner(), $this->getJWTSigningKey()) ->getToken(); diff --git a/app/Http/Middleware/Api/AuthenticateKey.php b/app/Http/Middleware/Api/AuthenticateKey.php index 0b6b23f7f..4b8156dd1 100644 --- a/app/Http/Middleware/Api/AuthenticateKey.php +++ b/app/Http/Middleware/Api/AuthenticateKey.php @@ -98,13 +98,17 @@ class AuthenticateKey } // Run through the token validation and throw an exception if the token is not valid. + // + // The issued_at time is used for verification in order to allow rapid changing of session + // length on the Panel without having to wait on existing tokens to first expire. + $now = Chronos::now('utc'); if ( - $token->getClaim('nbf') > Chronos::now()->getTimestamp() + Chronos::createFromTimestampUTC($token->getClaim('nbf'))->gt($now) || $token->getClaim('iss') !== 'Pterodactyl Panel' || $token->getClaim('aud') !== config('app.url') - || $token->getClaim('exp') <= Chronos::now()->getTimestamp() + || Chronos::createFromTimestampUTC($token->getClaim('iat'))->addMinutes(config('jwt.lifetime'))->lte($now) ) { - throw new AccessDeniedHttpException; + throw new AccessDeniedHttpException('The authentication parameters provided are not valid for accessing this resource.'); } return (new ApiKey)->forceFill([ diff --git a/config/jwt.php b/config/jwt.php index 6bd04a635..d51a7fae9 100644 --- a/config/jwt.php +++ b/config/jwt.php @@ -12,6 +12,7 @@ return [ | */ 'key' => env('APP_JWT_KEY'), + 'lifetime' => env('APP_JWT_LIFETIME', 1440), 'signer' => \Lcobucci\JWT\Signer\Hmac\Sha256::class, ]; diff --git a/resources/assets/scripts/app.js b/resources/assets/scripts/app.js index fe58baf9f..6048cc5aa 100644 --- a/resources/assets/scripts/app.js +++ b/resources/assets/scripts/app.js @@ -10,22 +10,21 @@ require('./bootstrap'); import { Ziggy } from './helpers/ziggy'; import Locales from './../../../resources/lang/locales'; import { flash } from './mixins/flash'; -import { routes } from './routes'; import store from './store/index.js'; +import router from './router'; window.events = new Vue; window.Ziggy = Ziggy; Vue.use(Vuex); +Vue.use(VueRouter); +Vue.use(vuexI18n.plugin, store); const route = require('./../../../vendor/tightenco/ziggy/src/js/route').default; Vue.mixin({ methods: { route } }); Vue.mixin(flash); -Vue.use(VueRouter); -Vue.use(vuexI18n.plugin, store); - Vue.i18n.add('en', Locales.en); Vue.i18n.set('en'); @@ -33,8 +32,4 @@ if (module.hot) { module.hot.accept(); } -const router = new VueRouter({ - mode: 'history', routes -}); - const app = new Vue({ store, router }).$mount('#pterodactyl'); diff --git a/resources/assets/scripts/models/user.js b/resources/assets/scripts/models/user.js index 149afd818..d4b338d95 100644 --- a/resources/assets/scripts/models/user.js +++ b/resources/assets/scripts/models/user.js @@ -9,17 +9,19 @@ export default class User { */ static fromToken(token) { if (!isString(token)) { - token = localStorage.getItem('token'); + token = this.getToken(); } if (!isString(token) || token.length < 1) { return null; } - const data = jwtDecode(token); - if (data.user) { - return new User(data.user); - } + try { + const data = jwtDecode(token); + if (data.user) { + return new User(data.user); + } + } catch (ex) {} return null; } @@ -29,8 +31,7 @@ export default class User { * * @returns {string | null} */ - static getToken() - { + static getToken() { return localStorage.getItem('token'); } @@ -60,4 +61,11 @@ export default class User { this.last_name = last_name; this.language = language; } + + /** + * Returns the JWT belonging to the current user. + */ + getJWT() { + return jwtDecode(User.getToken()); + } } diff --git a/resources/assets/scripts/router.js b/resources/assets/scripts/router.js new file mode 100644 index 000000000..2eaff883c --- /dev/null +++ b/resources/assets/scripts/router.js @@ -0,0 +1,81 @@ +import VueRouter from 'vue-router'; +import store from './store/index'; +import compareDate from 'date-fns/compare_asc' +import addHours from 'date-fns/add_hours' +import dateParse from 'date-fns/parse' +const route = require('./../../../vendor/tightenco/ziggy/src/js/route').default; + +// Base Vuejs Templates +import Login from './components/auth/Login'; +import Dashboard from './components/dashboard/Dashboard'; +import Account from './components/dashboard/Account'; +import ResetPassword from './components/auth/ResetPassword'; + +const routes = [ + { name: 'login', path: '/auth/login', component: Login }, + { name: 'forgot-password', path: '/auth/password', component: Login }, + { name: 'checkpoint', path: '/auth/checkpoint', component: Login }, + { + name: 'reset-password', + path: '/auth/password/reset/:token', + component: ResetPassword, + props: function (route) { + return { token: route.params.token, email: route.query.email || '' }; + } + }, + + { name : 'dashboard', path: '/', component: Dashboard }, + { name : 'account', path: '/account', component: Account }, + { name : 'account.api', path: '/account/api', component: Account }, + { name : 'account.security', path: '/account/security', component: Account }, + + { + name: 'server', + path: '/server/:id', + // component: Server, + // children: [ + // { path: 'files', component: ServerFileManager } + // ], + } +]; + +const router = new VueRouter({ + mode: 'history', routes +}); + +// Redirect the user to the login page if they try to access a protected route and +// have no JWT or the JWT is expired and wouldn't be accepted by the Panel. +router.beforeEach((to, from, next) => { + if (to.path === route('auth.logout')) { + return window.location = route('auth.logout'); + } + + const user = store.getters['auth/getUser']; + + // If user is trying to access the authentication endpoints but is already authenticated + // don't try to load them, just send the user to the dashboard. + if (to.path.startsWith('/auth')) { + if (user !== null && compareDate(addHours(dateParse(user.getJWT().iat * 1000), 12), new Date()) >= 0) { + return window.location = '/'; + } + + return next(); + } + + // If user is trying to access any of the non-authentication endpoints ensure that they have + // a valid, non-expired JWT. + if (!to.path.startsWith('/auth')) { + // Check if the JWT has expired. Don't use the exp field, but rather that issued at time + // so that we can adjust how long we want to wait for expiration on both server-side and + // client side without having to wait for older tokens to pass their expiration time if + // we lower it. + if (user === null || compareDate(addHours(dateParse(user.getJWT().iat * 1000), 12), new Date()) < 0) { + return window.location = route('auth.login'); + } + } + + // Continue on through the pipeline. + return next(); +}); + +export default router; diff --git a/resources/assets/scripts/store/index.js b/resources/assets/scripts/store/index.js index 7c7d87cbb..09c707244 100644 --- a/resources/assets/scripts/store/index.js +++ b/resources/assets/scripts/store/index.js @@ -4,7 +4,19 @@ import auth from './modules/auth'; Vue.use(Vuex); -export default new Vuex.Store({ +const store = new Vuex.Store({ strict: process.env.NODE_ENV !== 'production', modules: { auth }, }); + +if (module.hot) { + module.hot.accept(['./modules/auth'], () => { + const newAuthModule = require('./modules/auth').default; + + store.hotUpdate({ + modules: { newAuthModule }, + }); + }); +} + +export default store; diff --git a/routes/auth.php b/routes/auth.php index a6038447b..3ae4967be 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -8,7 +8,7 @@ | Endpoint: /auth | */ -Route::group(['middleware' => 'guest'], function () { +Route::group([], function () { // These routes are defined so that we can continue to reference them programatically. // They all route to the same controller function which passes off to Vuejs. Route::get('/login', 'LoginController@index')->name('auth.login'); From 1acedc2de2664d71e2b7ef84d39a5ed0d6d29318 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 16 Jun 2018 14:11:58 -0700 Subject: [PATCH 11/62] Remove luxon completely. --- package.json | 2 +- .../assets/scripts/components/dashboard/Dashboard.vue | 10 +++++----- yarn.lock | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index c918bc618..a727e3fa1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "pterodactyl-panel", "dependencies": { + "date-fns": "^1.29.0", "vue": "^2.5.7", "vue-axios": "^2.1.1", "vue-router": "^3.0.1", @@ -27,7 +28,6 @@ "jquery": "^3.3.1", "jwt-decode": "^2.2.0", "lodash": "^4.17.5", - "luxon": "^1.2.1", "postcss": "^6.0.21", "postcss-import": "^11.1.0", "postcss-loader": "^2.1.5", diff --git a/resources/assets/scripts/components/dashboard/Dashboard.vue b/resources/assets/scripts/components/dashboard/Dashboard.vue index 575b77006..479cf4bbc 100644 --- a/resources/assets/scripts/components/dashboard/Dashboard.vue +++ b/resources/assets/scripts/components/dashboard/Dashboard.vue @@ -28,9 +28,9 @@ diff --git a/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue b/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue index 0e4d82b69..d8932c973 100644 --- a/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue +++ b/resources/assets/scripts/components/dashboard/account/UpdateEmail.vue @@ -16,12 +16,6 @@ v-model="password" >
-
- - -
@@ -31,6 +25,7 @@ diff --git a/resources/assets/scripts/components/dashboard/Account.vue b/resources/assets/scripts/components/dashboard/Account.vue index 655acfb63..3b481a817 100644 --- a/resources/assets/scripts/components/dashboard/Account.vue +++ b/resources/assets/scripts/components/dashboard/Account.vue @@ -2,32 +2,18 @@
+ + +
- -
- -
-

Change your password

-
- - -
-
- - -

Your new password should be at least 8 characters in length, contain one number, and be mixed case.

-
-
- - -
-
- -
-
- +
+ +
+ +
+
@@ -36,16 +22,18 @@ diff --git a/resources/assets/scripts/components/dashboard/account/ChangePassword.vue b/resources/assets/scripts/components/dashboard/account/ChangePassword.vue new file mode 100644 index 000000000..52ad65a95 --- /dev/null +++ b/resources/assets/scripts/components/dashboard/account/ChangePassword.vue @@ -0,0 +1,31 @@ + + + diff --git a/resources/assets/scripts/components/dashboard/account/TwoFactorAuthentication.vue b/resources/assets/scripts/components/dashboard/account/TwoFactorAuthentication.vue new file mode 100644 index 000000000..6899e305b --- /dev/null +++ b/resources/assets/scripts/components/dashboard/account/TwoFactorAuthentication.vue @@ -0,0 +1,11 @@ + + + diff --git a/resources/assets/styles/components/animations.css b/resources/assets/styles/components/animations.css index a081fb4f7..a3daa6722 100644 --- a/resources/assets/styles/components/animations.css +++ b/resources/assets/styles/components/animations.css @@ -34,3 +34,15 @@ @apply .bg-red-dark; } } + +/* + * transition="modal" + */ +.modal-enter, .modal-leave-active { + opacity: 0; +} + +.modal-enter .modal-container, +.modal-leave-active .modal-container { + animation: opacity 250ms linear; +} diff --git a/resources/assets/styles/components/buttons.css b/resources/assets/styles/components/buttons.css index bc14f09d4..733efc0a5 100644 --- a/resources/assets/styles/components/buttons.css +++ b/resources/assets/styles/components/buttons.css @@ -12,6 +12,14 @@ } } + &.btn-green { + @apply .bg-green .border-green-dark .border .text-white; + + &:hover:enabled { + @apply .bg-green-dark .border-green-darker; + } + } + &.btn-secondary { @apply .border .border-grey-light .text-grey-dark; diff --git a/resources/assets/styles/components/modal.css b/resources/assets/styles/components/modal.css new file mode 100644 index 000000000..8a36e9592 --- /dev/null +++ b/resources/assets/styles/components/modal.css @@ -0,0 +1,10 @@ +.modal-mask { + @apply .fixed .pin .z-50 .overflow-auto .flex; + background: rgba(0, 0, 0, 0.7); + transition: opacity 250ms ease; + + & > .modal-container { + @apply .relative .p-8 .bg-white .w-full .max-w-md .m-auto .flex-col .flex; + transition: all 250ms ease; + } +} diff --git a/resources/assets/styles/main.css b/resources/assets/styles/main.css index 4a42cd267..0af5be78b 100644 --- a/resources/assets/styles/main.css +++ b/resources/assets/styles/main.css @@ -12,6 +12,7 @@ @import "components/buttons.css"; @import "components/forms.css"; @import "components/miscellaneous.css"; +@import "components/modal.css"; @import "components/navigation.css"; @import "components/notifications.css"; @import "components/spinners.css"; From 4e4a183f48b732eaac880cccaddfcb7ca8ed5bb2 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 16 Jun 2018 16:27:53 -0700 Subject: [PATCH 16/62] Put the modal more at the top, looks funky in middle --- resources/assets/styles/components/modal.css | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/assets/styles/components/modal.css b/resources/assets/styles/components/modal.css index 8a36e9592..5146021eb 100644 --- a/resources/assets/styles/components/modal.css +++ b/resources/assets/styles/components/modal.css @@ -6,5 +6,6 @@ & > .modal-container { @apply .relative .p-8 .bg-white .w-full .max-w-md .m-auto .flex-col .flex; transition: all 250ms ease; + margin-top: 15%; } } From ac7cefb83f9d6f3c5602716f61c406c932516d85 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 16 Jun 2018 16:43:52 -0700 Subject: [PATCH 17/62] Make the account page mobile friendly --- .../scripts/components/dashboard/Account.vue | 16 ++++++++++------ .../dashboard/account/ChangePassword.vue | 2 +- .../components/dashboard/account/UpdateEmail.vue | 2 +- .../assets/styles/components/miscellaneous.css | 7 +++++++ 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/resources/assets/scripts/components/dashboard/Account.vue b/resources/assets/scripts/components/dashboard/Account.vue index 3b481a817..b764dc1c6 100644 --- a/resources/assets/scripts/components/dashboard/Account.vue +++ b/resources/assets/scripts/components/dashboard/Account.vue @@ -6,14 +6,18 @@ -
-
- -
- +
+
+
+ +
+ +
- +
+ +
diff --git a/resources/assets/scripts/components/dashboard/account/ChangePassword.vue b/resources/assets/scripts/components/dashboard/account/ChangePassword.vue index 52ad65a95..c9f8944a7 100644 --- a/resources/assets/scripts/components/dashboard/account/ChangePassword.vue +++ b/resources/assets/scripts/components/dashboard/account/ChangePassword.vue @@ -1,7 +1,7 @@