Passed
Push — master ( eecc1f...7de1eb )
by Russell
08:40
created

VerifiableExtension::read()   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 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @author  Russell Michell 2018 <[email protected]>
5
 * @package silverstripe-verifiable
6
 */
7
8
namespace PhpTek\Verifiable\Verify;
9
10
use SilverStripe\Core\DataExtension;
0 ignored issues
show
Bug introduced by
The type SilverStripe\Core\DataExtension was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use PhpTek\JSONText\JSONText;
0 ignored issues
show
Bug introduced by
The type PhpTek\JSONText\JSONText was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
13
/**
14
 * By attaching to any {@link DataObject} subclass, including {@link SiteTree}
15
 * subclasses, and declaring a $verifiable_fields array in YML config, all subsequent
16
 * database writes will be passed through here via onAfterWrite();
17
 *
18
 * This {@link DataExtension} also provides a single field to which all verifiable
19
 * chainpoint proofs are stored in a queryable JSON-aware field.
20
 *
21
 * @todo Flag to API users that confirmation has not yet occurred.
22
 * @todo Store the hash function used and if subsequent verifications
23
 *       fail because differing hash functions are used, throw an exception
24
 */
25
class VerifiableExtension extends DataExtension
26
{
27
    /**
28
     * Declare a field on this owner where all chainpoint proofs should be stored.
29
     *
30
     * @var array
31
     * @config
32
     */
33
    private static $db = [
0 ignored issues
show
introduced by
The private property $db is not used, and could be removed.
Loading history...
34
        'Proofs' => JSONText::class,
35
    ];
36
37
    /**
38
     * These field's values will be hashed and committed to the current backend.
39
     *
40
     * @var array
41
     * @config
42
     */
43
    private static $verifiable_fields = [];
0 ignored issues
show
introduced by
The private property $verifiable_fields is not used, and could be removed.
Loading history...
44
45
    /**
46
     * After each write, the desired field's data is compiled into a string
47
     * and submitted to the currently configured backend.
48
     *
49
     * @return void
50
     */
51
    public function onAfterWrite()
52
    {
53
        parent::onAfterWrite();
54
55
        $fields = $this->getOwner()->config()->get('verifiable_fields');
56
        $verifiable = [];
57
58
        foreach ($fields as $field) {
59
            $verifiable[] = (string) $this->getOwner()->getField($field);
60
        }
61
62
        if (count($verifiable)) {
63
            $this->verifiableService->write($verifiable);
64
        }
65
    }
66
67
    /**
68
     * Central to the whole package, this method is passed an array of fields
69
     * and their values, hashes them and will check that a chainpoint proof
70
     * exists in the local database. If unsuccessful, we return false.
71
     * Otherwise, we continue and consult the backend for the same proof. If one
72
     * is found both locally and in the backed, then the supplied data is said to
73
     * be verified. Note: See the $strict param to skip the local proof check.
74
     *
75
     * @param  array  $data   An array of data to verify against the current backend.
76
     * @param  bool   $strict True by default; That-is both the local database and
77
     *                        the backend are consulted for a valid proof. If set
78
     *                        to false, we bypass the local check and just consult
79
     *                        the backend directly.
80
     * @return bool           True if the backend verifies the proof, false otherwise.
81
     */
82
    public function verify(array $data, bool $strict = true) : bool
83
    {
84
        $hash = $this->verifiableService->hash($data);
85
86
        // 1). Get the locally stored chainpoint proof
87
        if (!$localProof = $this->getOwner()->getField('Proof')->find('>>hash', $hash)) {
88
            return false;
89
        }
90
91
        // 2). Send the local proof to the backend for verification
92
        if (!$this->verificationService->verify($localProof)) {
93
            return false;
94
        }
95
96
        // 3). Verification complete
97
        return true;
98
    }
99
100
}
101
102