Skip to content

Commit d63624f

Browse files
committed
Working login form with password reset functionality.
1 parent c3e462a commit d63624f

File tree

21 files changed

+232
-324
lines changed

21 files changed

+232
-324
lines changed

app/Http/Controllers/Auth/AbstractLoginController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ protected function sendFailedLoginResponse(Request $request, Authenticatable $us
107107
]);
108108

109109
if ($request->route()->named('auth.checkpoint')) {
110-
throw new DisplayException(trans('auth.checkpoint_failed'));
110+
throw new DisplayException(trans('auth.two_factor.checkpoint_failed'));
111111
}
112112

113113
throw new DisplayException(trans('auth.failed'));

app/Http/Controllers/Auth/LoginCheckpointController.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class LoginCheckpointController extends AbstractLoginController
1818
*
1919
* @throws \Pterodactyl\Exceptions\DisplayException
2020
*/
21-
public function index(LoginCheckpointRequest $request): JsonResponse
21+
public function __invoke(LoginCheckpointRequest $request): JsonResponse
2222
{
2323
try {
2424
$cache = $this->cache->pull($request->input('confirmation_token'), []);

app/Http/Controllers/Auth/LoginController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public function login(Request $request): JsonResponse
2222
$username = $request->input('user');
2323
$useColumn = $this->getField($username);
2424

25+
sleep(1);
26+
2527
if ($this->hasTooManyLoginAttempts($request)) {
2628
$this->fireLockoutEvent($request);
2729
$this->sendLockoutResponse($request);

app/Http/Controllers/Auth/ResetPasswordController.php

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
namespace Pterodactyl\Http\Controllers\Auth;
44

5+
use Illuminate\Http\JsonResponse;
6+
use Illuminate\Support\Facades\Password;
7+
use Pterodactyl\Exceptions\DisplayException;
58
use Pterodactyl\Http\Controllers\Controller;
69
use Illuminate\Foundation\Auth\ResetsPasswords;
10+
use Pterodactyl\Http\Requests\Auth\ResetPasswordRequest;
711

812
class ResetPasswordController extends Controller
913
{
@@ -17,16 +21,44 @@ class ResetPasswordController extends Controller
1721
public $redirectTo = '/';
1822

1923
/**
20-
* Return the rules used when validating password reset.
24+
* Reset the given user's password.
2125
*
22-
* @return array
26+
* @param \Pterodactyl\Http\Requests\Auth\ResetPasswordRequest $request
27+
* @return \Illuminate\Http\JsonResponse
28+
*
29+
* @throws \Pterodactyl\Exceptions\DisplayException
30+
*/
31+
public function __invoke(ResetPasswordRequest $request): JsonResponse
32+
{
33+
// Here we will attempt to reset the user's password. If it is successful we
34+
// will update the password on an actual user model and persist it to the
35+
// database. Otherwise we will parse the error and return the response.
36+
$response = $this->broker()->reset(
37+
$this->credentials($request), function ($user, $password) {
38+
$this->resetPassword($user, $password);
39+
}
40+
);
41+
42+
// If the password was successfully reset, we will redirect the user back to
43+
// the application's home authenticated view. If there is an error we can
44+
// redirect them back to where they came from with their error message.
45+
if ($response === Password::PASSWORD_RESET) {
46+
return $this->sendResetResponse();
47+
}
48+
49+
throw new DisplayException(trans($response));
50+
}
51+
52+
/**
53+
* Send a successful password reset response back to the callee.
54+
*
55+
* @return \Illuminate\Http\JsonResponse
2356
*/
24-
protected function rules(): array
57+
protected function sendResetResponse(): JsonResponse
2558
{
26-
return [
27-
'token' => 'required',
28-
'email' => 'required|email',
29-
'password' => 'required|confirmed|min:8',
30-
];
59+
return response()->json([
60+
'success' => true,
61+
'redirect_to' => $this->redirectTo,
62+
]);
3163
}
3264
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Pterodactyl\Http\Requests\Auth;
4+
5+
use Illuminate\Foundation\Http\FormRequest;
6+
7+
class ResetPasswordRequest extends FormRequest
8+
{
9+
/**
10+
* @return bool
11+
*/
12+
public function authorize(): bool
13+
{
14+
return true;
15+
}
16+
17+
/**
18+
* @return array
19+
*/
20+
public function rules(): array
21+
{
22+
return [
23+
'token' => 'required|string',
24+
'email' => 'required|email',
25+
'password' => 'required|string|confirmed|min:8',
26+
];
27+
}
28+
}

gulpfile.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const paths = {
2323
},
2424
scripts: {
2525
src: './resources/assets/pterodactyl/scripts/**/*.{js,vue}',
26+
watch: ['./resources/assets/pterodactyl/scripts/**/*.{js,vue}', './resources/lang/locales.js'],
2627
dest: './public/assets/scripts',
2728
},
2829
};
@@ -68,7 +69,7 @@ function watch() {
6869
return del(['./public/assets/css/**/*.css']);
6970
}, styles));
7071

71-
gulp.watch(paths.scripts.src, gulp.series(function cleanScripts() {
72+
gulp.watch(paths.scripts.watch, gulp.series(function cleanScripts() {
7273
return del(['./public/assets/scripts/**/*.js']);
7374
}, scripts));
7475
}

resources/assets/pterodactyl/scripts/app.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Locales from './../../../../resources/lang/locales';
1111

1212
// Base Vuejs Templates
1313
import Login from './components/auth/Login';
14+
import ResetPassword from './components/auth/ResetPassword';
1415

1516
// Used for the route() helper.
1617
window.Ziggy = Ziggy;
@@ -58,6 +59,17 @@ const router = new VueRouter({
5859
path: '/checkpoint',
5960
component: Login,
6061
},
62+
{
63+
name: 'reset-password',
64+
path: '/reset-password/:token',
65+
component: ResetPassword,
66+
props: function (route) {
67+
return {
68+
token: route.params.token,
69+
email: route.query.email || '',
70+
}
71+
},
72+
}
6173
]
6274
});
6375

resources/assets/pterodactyl/scripts/components/auth/ForgotPassword.vue

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,20 @@
1313
<div class="flex flex-wrap -mx-3 mb-6">
1414
<div class="input-open">
1515
<input class="input" id="grid-email" type="email" aria-labelledby="grid-email" ref="email" required
16+
v-bind:class="{ 'has-content': email.length > 0 }"
1617
v-bind:readonly="showSpinner"
1718
v-bind:value="email"
1819
v-on:input="updateEmail($event)"
1920
/>
2021
<label for="grid-email">{{ $t('strings.email') }}</label>
21-
<p class="text-grey-darker text-xs">{{ $t('auth.reset_help_text') }}</p>
22+
<p class="text-grey-darker text-xs">{{ $t('auth.forgot_password.label_help') }}</p>
2223
</div>
2324
</div>
2425
<div>
2526
<button class="btn btn-blue btn-jumbo" type="submit" v-bind:disabled="submitDisabled">
2627
<span class="spinner white" v-bind:class="{ hidden: ! showSpinner }">&nbsp;</span>
2728
<span v-bind:class="{ hidden: showSpinner }">
28-
{{ $t('auth.recover_account') }}
29+
{{ $t('auth.forgot_password.button') }}
2930
</span>
3031
</button>
3132
</div>
@@ -67,7 +68,7 @@
6768
this.$data.showSpinner = true;
6869
this.$data.errors = [];
6970
70-
window.axios.post(this.route('auth.forgot-password.send-link'), {
71+
window.axios.post(this.route('auth.forgot-password'), {
7172
email: this.$props.email,
7273
})
7374
.then(function (response) {

resources/assets/pterodactyl/scripts/components/auth/Login.vue

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,7 @@
1010
v-bind:email="user.email"
1111
v-on:update-email="onUpdateEmail"
1212
/>
13-
<two-factor-form
14-
v-if="this.$route.name === 'checkpoint'"
15-
/>
13+
<two-factor-form v-if="this.$route.name === 'checkpoint'" />
1614
</div>
1715
</template>
1816

resources/assets/pterodactyl/scripts/components/auth/LoginForm.vue

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
<div>
33
<flash-message variant="danger" />
44
<flash-message variant="success" />
5-
<div class="pb-4" v-if="errors && errors.length === 1">
5+
<div class="pb-4" v-for="error in errors">
66
<div class="p-2 bg-red-dark border-red-darker border items-center text-red-lightest leading-normal rounded flex lg:inline-flex w-full text-sm"
77
role="alert">
88
<span class="flex rounded-full bg-red uppercase px-2 py-1 text-xs font-bold mr-3 leading-none">Error</span>
9-
<span class="mr-2 text-left flex-auto">{{ errors[0] }}</span>
9+
<span class="mr-2 text-left flex-auto">{{ error }}</span>
1010
</div>
1111
</div>
1212
<form class="bg-white shadow-lg rounded-lg pt-10 px-8 pb-6 mb-4 animate fadein" method="post"
@@ -16,6 +16,7 @@
1616
<div class="input-open">
1717
<input class="input" id="grid-username" type="text" name="user" aria-labelledby="grid-username" required
1818
ref="email"
19+
v-bind:readonly="showSpinner"
1920
v-bind:value="user.email"
2021
v-on:input="updateEmail($event)"
2122
/>
@@ -26,6 +27,7 @@
2627
<div class="input-open">
2728
<input class="input" id="grid-password" type="password" name="password"
2829
ref="password"
30+
v-bind:readonly="showSpinner"
2931
aria-labelledby="grid-password" required
3032
v-model="user.password"
3133
/>
@@ -43,7 +45,7 @@
4345
<div class="pt-6 text-center">
4446
<router-link class="text-xs text-grey tracking-wide no-underline uppercase hover:text-grey-dark"
4547
:to="{ name: 'forgot-password' }">
46-
{{ $t('auth.forgot_password') }}
48+
{{ $t('auth.forgot_password.label') }}
4749
</router-link>
4850
</div>
4951
</form>

0 commit comments

Comments
 (0)