Skip to content

Commit

Permalink
Add mutation to update the current user's password
Browse files Browse the repository at this point in the history
  • Loading branch information
wimski committed Jun 22, 2021
1 parent 08d1666 commit f0cecde
Show file tree
Hide file tree
Showing 5 changed files with 618 additions and 0 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ Make sure the following middleware is enabled for Lighthouse:
- [Resend Email Verification Link](#resend-email-verification-link)
- [Forgot Password](#forgot-password)
- [Reset Password](#reset-password)
- [Update Password](#update-password)

### Login

Expand Down Expand Up @@ -279,6 +280,21 @@ mutation {

<img src="https://user-images.githubusercontent.com/3015394/116374360-8045d200-a80e-11eb-891b-c9395d4e91a0.png" height="160">

### Update Password

Updates the current user's password.

```graphql
mutation {
updatePassword(input: {
current_password: "mypass",
password: "secret",
password_confirmation: "secret"
}) {
status
}
}
```

## Testing

Expand Down
17 changes: 17 additions & 0 deletions graphql/sanctum.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,21 @@ enum ResetPasswordStatus {
PASSWORD_RESET
}

input UpdatePasswordInput {
current_password: String!
password: String! @rules(apply: ["confirmed"])
password_confirmation: String!
}

type UpdatePasswordResponse {
status: UpdatePasswordStatus!
}

enum UpdatePasswordStatus {
"""PASSWORD_UPDATED"""
PASSWORD_UPDATED
}

extend type Mutation {
login(input: LoginInput @spread): AccessToken!
@field(resolver: "DanielDeWit\\LighthouseSanctum\\GraphQL\\Mutations\\Login")
Expand All @@ -146,4 +161,6 @@ extend type Mutation {
@field(resolver: "DanielDeWit\\LighthouseSanctum\\GraphQL\\Mutations\\ForgotPassword")
resetPassword(input: ResetPasswordInput! @spread): ResetPasswordResponse!
@field(resolver: "DanielDeWit\\LighthouseSanctum\\GraphQL\\Mutations\\ResetPassword")
updatePassword(input: UpdatePasswordInput! @spread): UpdatePasswordResponse! @guard
@field(resolver: "DanielDeWit\\LighthouseSanctum\\GraphQL\\Mutations\\UpdatePassword")
}
99 changes: 99 additions & 0 deletions src/GraphQL/Mutations/UpdatePassword.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

declare(strict_types=1);

namespace DanielDeWit\LighthouseSanctum\GraphQL\Mutations;

use DanielDeWit\LighthouseSanctum\Exceptions\GraphQLValidationException;
use DanielDeWit\LighthouseSanctum\Traits\HasAuthenticatedUser;
use DanielDeWit\LighthouseSanctum\Traits\HasUserModel;
use Exception;
use GraphQL\Type\Definition\ResolveInfo;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Factory as AuthFactory;
use Illuminate\Contracts\Hashing\Hasher;
use Illuminate\Contracts\Translation\Translator;
use Nuwave\Lighthouse\Support\Contracts\GraphQLContext;

class UpdatePassword
{
use HasAuthenticatedUser;
use HasUserModel;

protected AuthFactory $authFactory;
protected Hasher $hasher;
protected Translator $translator;
protected ResolveInfo $resolveInfo;

public function __construct(AuthFactory $authFactory, Hasher $hasher, Translator $translator)
{
$this->authFactory = $authFactory;
$this->hasher = $hasher;
$this->translator = $translator;
}

/**
* @param mixed $_
* @param array<string, mixed> $args
* @param GraphQLContext $context
* @param ResolveInfo $resolveInfo
* @return array<string, string>
* @throws Exception
*/
public function __invoke($_, array $args, GraphQLContext $context, ResolveInfo $resolveInfo): array
{
$this->resolveInfo = $resolveInfo;

$user = $this->getAuthenticatedUser();

$this->currentPasswordMustBeTheSame($user, $args['current_password']);
$this->newPasswordMustBeDifferent($user, $args['password']);

$this->getModelFromUser($user)->update([
'password' => $this->hasher->make($args['password']),
]);

return [
'status' => 'PASSWORD_UPDATED',
];
}

/**
* @param Authenticatable $user
* @param string $currentPassword
* @throws GraphQLValidationException
*/
protected function currentPasswordMustBeTheSame(Authenticatable $user, string $currentPassword): void
{
if (! $this->hasher->check($currentPassword, $user->getAuthPassword())) {
$message = $this->translator->get('validation.same', [
'attribute' => 'current_password',
'other' => 'user password',
]);

throw new GraphQLValidationException($message, 'current_password', $this->resolveInfo);
}
}

/**
* @param Authenticatable $user
* @param string $newPassword
* @throws GraphQLValidationException
*/
protected function newPasswordMustBeDifferent(Authenticatable $user, string $newPassword): void
{
if ($this->hasher->check($newPassword, $user->getAuthPassword())) {
$message = $this->translator->get('validation.different', [
'attribute' => 'password',
'other' => 'user password',
]);

throw new GraphQLValidationException($message, 'password', $this->resolveInfo);
}
}

protected function getAuthFactory(): AuthFactory
{
return $this->authFactory;
}
}
Loading

0 comments on commit f0cecde

Please sign in to comment.