Failed Conditions
Push — master ( 1b92c1...5e8dd9 )
by Arnold
03:03
created

Confirmation::getConfirmationToken()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 7
cts 7
cp 1
rs 9.4285
c 0
b 0
f 0
nc 1
cc 1
eloc 7
nop 2
crap 1
1
<?php
2
3
namespace Jasny\Auth;
4
5
use Hashids\Hashids;
6
7
/**
8
 * Generate and verify confirmation tokens.
9
 * 
10
 * Uses the hashids library.
11
 * @link http://hashids.org/php/
12
 * 
13
 * <code>
14
 * class Auth extends Jasny\Auth
15
 * {
16
 *   use Jasny\Auth\Confirmation;
17
 * 
18
 *   public function getConfirmationSecret()
19
 *   {
20
 *     return "f)lk3sd^92qlj$%f8321*(&lk";
21
 *   }
22
 * 
23
 *   ...
24
 * }
25
 * </code>
26
 */
27
trait Confirmation
28
{
29
    /**
30
     * Fetch a user by ID
31
     * 
32
     * @param int|string $id
33
     * @return User|null
34
     */
35
    abstract public function fetchUserById($id);
36
    
37
    /**
38
     * Get secret for the confirmation hash
39
     * 
40
     * @return string
41
     */
42
    abstract protected function getConfirmationSecret();
43
44
    
45
    /**
46
     * Create a heashids interface
47
     * 
48
     * @param string $secret
0 ignored issues
show
Bug introduced by
There is no parameter named $secret. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
49
     * @return Hashids
50
     */
51 7
    protected function createHashids($subject)
52
    {
53 7
        if (!class_exists(Hashids::class)) {
54
            // @codeCoverageIgnoreStart
55
            throw new \Exception("Unable to generate a confirmation hash: Hashids library is not installed");
56
            // @codeCoverageIgnoreEnd
57
        }
58
        
59 7
        $salt = hash('sha256', $this->getConfirmationSecret() . $subject);
60
        
61 7
        return new Hashids($salt);
62
    }
63
    
64
    /**
65
     * Generate a confirm hash based on a user id
66
     * 
67
     * @param string $id
68
     * @return int
69
     */
70 4
    protected function generateConfirmHash($id)
71
    {
72 4
        $confirmHash = md5($id . $this->getConfirmationSecret());
73
        
74 4
        return hexdec(substr($confirmHash, 0, 8));
75
    }
76
    
77
    /**
78
     * Generate a confirmation token
79
     * 
80
     * @param User   $user
81
     * @param string $subject  What needs to be confirmed?
82
     * @return string
83
     */
84 2
    public function getConfirmationToken(User $user, $subject)
85
    {
86 2
        $hashids = $this->createHashids($subject);
87
        
88 2
        $id = $user->getId();
89 2
        $confirm = $this->generateConfirmHash($id);
90
        
91 2
        $parts = array_map('hexdec', str_split($id, 8)); // Will work if id is hexidecimal or decimal
92 2
        $parts[] = $confirm;
93
        
94 2
        return $hashids->encode($parts);
95
    }
96
    
97
    /**
98
     * Get user by confirmation hash
99
     * 
100
     * @param string $token    Confirmation token
101
     * @param string $subject  What needs to be confirmed?
102
     * @return User|null
103
     */
104 5
    public function fetchUserForConfirmation($token, $subject)
105
    {
106 5
        $hashids = $this->createHashids($subject);
107
        
108 5
        $parts = $hashids->decode($token);
109
        
110 5
        if (empty($parts)) {
111 3
            return null;
112
        }
113
        
114 2
        $confirm = array_pop($parts);
115 2
        $id = join(array_map('dechex', $parts));
116
        
117 2
        if ($confirm !== $this->generateConfirmHash($id)) {
118
            return null;
119
        }
120
121 2
        return $this->fetchUserById($id);
122
    }
123
}
124