Completed
Push — master ( 8e9653...be1e88 )
by Philip
02:27
created

UserSetup::getPWHashFunction()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
c 3
b 0
f 0
dl 0
loc 23
rs 9.0856
cc 3
eloc 14
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 = $that->possibleGenSalt($salt, $entity, $saltField);
48
49
            $passwordHash = $encoder->encodePassword($password, $salt);
50
51
            $doGenerateHash = $that->doGenerateHash($data, $entity, $passwordField, $password, $newSalt);
52
53
            if ($doGenerateHash) {
54
                $entity->set($passwordField, $passwordHash);
55
            }
56
            return true;
57
        };
58
    }
59
60
    /**
61
     * Generates a new salt if the given salt is null.
62
     *
63
     * @param string $salt
64
     * the salt to override if null
65
     * @param Entity
66
     * the entity getting the new salt
67
     * @param string $saltField
68
     * the field holding the salt in the entity
69
     *
70
     * @return boolean
71
     * true if a new salt was generated
72
     */
73
    public function possibleGenSalt(&$salt, Entity $entity, $saltField) {
74
        if (!$salt) {
75
            $salt = $this->getSalt(40);
76
            $entity->set($saltField, $salt);
77
            return true;
78
        }
79
        return false;
80
    }
81
82
    /**
83
     * Determines whether the entity needs a new hash generated.
84
     *
85
     * @param Data $data
86
     * the CRUDlex data instance of the user entity
87
     * @param Entity $entity
88
     * the entity
89
     * @param string $passwordField
90
     * the field holding the password hash in the entity
91
     * @param string $password
92
     * the current password hash
93
     * @param boolean $newSalt
94
     * whether a new password hash salt was generated
95
     *
96
     * @return boolean
97
     * true if the entity needs a new hash
98
     */
99
    public function doGenerateHash(Data $data, Entity $entity, $passwordField, $password, $newSalt) {
100
        $doGenerateHash = true;
101
        $id = $entity->get('id');
102
        if ($id !== null) {
103
            $oldEntity = $data->get($entity->get('id'));
104
            $doGenerateHash = $oldEntity->get($passwordField) !== $password || $newSalt;
105
        }
106
        return $doGenerateHash;
107
    }
108
109
    /**
110
     * Generates a random salt of the given length.
111
     *
112
     * @param int $len
113
     * the desired length
114
     *
115
     * @return string
116
     * a random salt of the given length
117
     */
118
    public function getSalt($len) {
119
        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789`~!@#$%^&*()-=_+';
120
        $l = strlen($chars) - 1;
121
        $str = '';
122
        for ($i = 0; $i < $len; ++$i) {
123
            $str .= $chars[mt_rand(0, $l)];
124
        }
125
        return $str;
126
    }
127
128
    /**
129
     * Setups CRUDlex with some events so the passwords get salted and
130
     * hashed properly.
131
     *
132
     * @param Data $data
133
     * the Data instance managing the users
134
     *
135
     * @param string $passwordField
136
     * the Entity fieldname of the password hash
137
     *
138
     * @param string $saltField
139
     * the Entity fieldname of the password hash salt
140
     */
141
    public function addEvents(Data $data, $passwordField = 'password', $saltField = 'salt') {
142
143
        $that = $this;
144
        $saltGenFunction = function(Entity $entity) use ($saltField, $that) {
145
            $salt = $that->getSalt(40);
146
            $entity->set($saltField, $salt);
147
            return true;
148
        };
149
150
        $data->pushEvent('before', 'create', $saltGenFunction);
151
152
        $pwHashFunction = $this->getPWHashFunction($data, $passwordField, $saltField);
153
154
        $data->pushEvent('before', 'create', $pwHashFunction);
155
        $data->pushEvent('before', 'update', $pwHashFunction);
156
157
    }
158
159
}
160