Completed
Push — master ( 049beb...2227f7 )
by Philip
02:26
created

UserSetup::doGenerateHash()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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