Passed
Pull Request — master (#24)
by Damian
03:43
created

AnonymousUserAuthenticator::checkPassword()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Firesphere\GraphQLJWT\Authentication;
4
5
use BadMethodCallException;
6
use SilverStripe\Control\HTTPRequest;
7
use SilverStripe\Core\Config\Configurable;
8
use SilverStripe\Core\Injector\Injectable;
9
use SilverStripe\ORM\ValidationException;
10
use SilverStripe\ORM\ValidationResult;
11
use SilverStripe\Security\Authenticator;
12
use SilverStripe\Security\Member;
13
use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator;
14
15
class AnonymousUserAuthenticator extends MemberAuthenticator
16
{
17
    use Configurable;
18
    use Injectable;
19
20
    /**
21
     * Anonymous username
22
     *
23
     * @var string
24
     */
25
    private static $anonymous_username = 'anonymous';
26
27
    /**
28
     * Default field values to assign to anonymous user
29
     *
30
     * @var array
31
     */
32
    private static $anonymous_fields = [
33
        'FirstName' => 'Anonymous',
34
    ];
35
36
    public function supportedServices(): int
37
    {
38
        return Authenticator::LOGIN | Authenticator::LOGOUT;
39
    }
40
41
    public function authenticate(array $data, HTTPRequest $request, ValidationResult &$result = null): ?Member
42
    {
43
        // Only applies to request for anonymous user specifically
44
        $email = $data['Email'] ?? null;
45
        if ($email !== static::config()->get('anonymous_username')) {
46
            return null;
47
        }
48
49
        return parent::authenticate($data, $request, $result);
50
    }
51
52
    /**
53
     * Attempt to find and authenticate member if possible from the given data
54
     *
55
     * @skipUpgrade
56
     * @param array            $data Form submitted data
57
     * @param ValidationResult $result
58
     * @param Member           $member This third parameter is used in the CMSAuthenticator(s)
59
     * @return Member Found member, regardless of successful login
60
     * @throws ValidationException
61
     */
62
    protected function authenticateMember($data, ValidationResult &$result = null, Member $member = null): Member
63
    {
64
        // Get user, or create if not exists
65
        $member = $this->getOrCreateAnonymousMember();
66
67
        // Validate this member is still allowed to login
68
        $result = $result ?: ValidationResult::create();
69
        $member->validateCanLogin($result);
70
71
        // Emit failure to member and form (if available)
72
        if ($result->isValid()) {
73
            $member->registerSuccessfulLogin();
74
        } else {
75
            $member->registerFailedLogin();
76
        }
77
78
        return $member;
79
    }
80
81
    public function checkPassword(Member $member, $password, ValidationResult &$result = null)
82
    {
83
        throw new BadMethodCallException("checkPassword not supported for anonymous users");
84
    }
85
86
    /**
87
     * Build a new datarecord to contain the anonymous user
88
     *
89
     * @return Member
90
     * @throws ValidationException
91
     */
92
    protected function getOrCreateAnonymousMember()
93
    {
94
        // Fun facts about anonymous members
95
        $identifierField = Member::config()->get('unique_identifier_field');
96
        $username = static::config()->get('anonymous_username');
97
        $fields = static::config()->get('anonymous_fields');
98
99
        // Find existing member
100
        /** @var Member $member */
101
        $member = Member::get()->find($identifierField, $username);
102
        $this->extend('updateExistingAnonymousMember', $member);
103
        if ($member) {
104
            return $member;
105
        }
106
107
        // Create new member
108
        $member = Member::create();
109
        $member->{$identifierField} = $username;
110
        $member->update($fields);
111
        $this->extend('updateCreatedAnonymousMember', $member);
112
        $member->write();
113
        return $member;
114
    }
115
}
116