Completed
Push — master ( 4df0d1...8e9653 )
by Philip
02:24
created

UserSetup::getPWHashFunction()   B

Complexity

Conditions 4
Paths 1

Size

Total Lines 28
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 28
rs 8.5806
cc 4
eloc 18
nc 1
nop 3
1
<?php
2
3
/*
4
 * This file is part of the CRUDlexUser package.
5
 *
6
 * (c) Philip Lehmann-Böhm <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace CRUDlex;
13
14
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
15
use CRUDlex\Data;
16
use CRUDlex\Entity;
17
18
/**
19
 * This class setups CRUDlex with some events so the passwords get salted and
20
 * hashed properly.
21
 */
22
class UserSetup {
23
24
    /**
25
     * Gets a closure for possibly generating a password hash in the entity.
26
     *
27
     * @param Data $data
28
     * the Data instance managing the users
29
     *
30
     * @param string $passwordField
31
     * the Entity fieldname of the password hash
32
     *
33
     * @param string $saltField
34
     * the Entity fieldname of the password hash salt
35
     */
36
    protected function getPWHashFunction(Data $data, $passwordField, $saltField) {
37
        $that = $this;
38
        return function(Entity $entity) use ($data, $passwordField, $saltField, $that) {
39
            $password = $entity->get($passwordField);
40
41
            if (!$password) {
42
                return true;
43
            }
44
45
            $encoder = new MessageDigestPasswordEncoder();
46
            $salt = $entity->get($saltField);
47
            $newSalt = false;
48
            if (!$salt) {
49
                $salt = $that->getSalt(40);
50
                $entity->set($saltField, $salt);
51
                $newSalt = true;
52
            }
53
54
            $passwordHash = $encoder->encodePassword($password, $salt);
55
56
            $doGenerateHash = $that->doGenerateHash($data, $entity, $passwordField, $password, $newSalt);
57
58
            if ($doGenerateHash) {
59
                $entity->set($passwordField, $passwordHash);
60
            }
61
            return true;
62
        };
63
    }
64
65
    /**
66
     * Determines whether the entity needs a new hash generated.
67
     *
68
     * @param Data $data
69
     * the CRUDlex data instance of the user entity
70
     * @param Entity $entity
71
     * the entity
72
     * @param string $passwordField
73
     * the field holding the password hash in the entity
74
     * @param string $password
75
     * the current password hash
76
     * @param boolean $newSalt
77
     * whether a new password hash salt was generated
78
     *
79
     * @return boolean
80
     * true if the entity needs a new hash
81
     */
82
    public function doGenerateHash(Data $data, Entity $entity, $passwordField, $password, $newSalt) {
83
        $doGenerateHash = true;
84
        $id = $entity->get('id');
85
        if ($id !== null) {
86
            $oldEntity = $data->get($entity->get('id'));
87
            $doGenerateHash = $oldEntity->get($passwordField) !== $password || $newSalt;
88
        }
89
        return $doGenerateHash;
90
    }
91
92
    /**
93
     * Generates a random salt of the given length.
94
     *
95
     * @param int $len
96
     * the desired length
97
     *
98
     * @return string
99
     * a random salt of the given length
100
     */
101
    public function getSalt($len) {
102
        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*()-=_+';
103
        $l = strlen($chars) - 1;
104
        $str = '';
105
        for ($i = 0; $i < $len; ++$i) {
106
            $str .= $chars[mt_rand(0, $l)];
107
        }
108
        return $str;
109
    }
110
111
    /**
112
     * Setups CRUDlex with some events so the passwords get salted and
113
     * hashed properly.
114
     *
115
     * @param Data $data
116
     * the Data instance managing the users
117
     *
118
     * @param string $passwordField
119
     * the Entity fieldname of the password hash
120
     *
121
     * @param string $saltField
122
     * the Entity fieldname of the password hash salt
123
     */
124
    public function addEvents(Data $data, $passwordField = 'password', $saltField = 'salt') {
125
126
        $that = $this;
127
        $saltGenFunction = function(Entity $entity) use ($saltField, $that) {
128
            $salt = $that->getSalt(40);
129
            $entity->set($saltField, $salt);
130
            return true;
131
        };
132
133
        $data->pushEvent('before', 'create', $saltGenFunction);
134
135
        $pwHashFunction = $this->getPWHashFunction($data, $passwordField, $saltField);
136
137
        $data->pushEvent('before', 'create', $pwHashFunction);
138
        $data->pushEvent('before', 'update', $pwHashFunction);
139
140
    }
141
142
}
143