Passed
Pull Request — master (#16)
by Tim
02:29
created

AttributeAddFromLDAP::process()   D

Complexity

Conditions 19
Paths 54

Size

Total Lines 83
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 19
eloc 52
c 1
b 0
f 0
nc 54
nop 1
dl 0
loc 83
rs 4.5166

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Filter to add attributes to the identity by executing a query against an LDAP directory
5
 *
6
 * Original Author: Steve Moitozo II <[email protected]>
7
 * Created: 20100513
8
 * Updated: 20100920 Steve Moitozo II
9
 *          - incorporated feedback from Olav Morken to prep code for inclusion in SimpleSAMLphp distro
10
 *          - moved call to ldap_set_options() inside test for $ds
11
 *          - added the output of ldap_error() to the exceptions
12
 *          - reduced some of the nested ifs
13
 *          - added support for multiple values
14
 *          - added support for anonymous binds
15
 *          - added escaping of search filter and attribute
16
 * Updated: 20111118 Ryan Panning
17
 *          - Updated the class to use BaseFilter which reuses LDAP connection features
18
 *          - Added conversion of original filter option names for backwards-compatibility
19
 *          - Updated the constructor to use the new config method
20
 *          - Updated the process method to use the new config variable names
21
 * Updated: 20131119 Yørn de Jong / Jaime Perez
22
 *          - Added support for retrieving multiple values at once from LDAP
23
 *          - Don't crash but fail silently on LDAP errors; the plugin is to complement attributes
24
 * Updated: 20161223 Remy Blom <[email protected]>
25
 *          - Adjusted the silent fail so it does show a warning in log when $this->getLdap() fails
26
 *
27
 * @author Yørn de Jong
28
 * @author Jaime Perez
29
 * @author Steve Moitozo
30
 * @author JAARS, Inc.
31
 * @author Ryan Panning
32
 * @author Remy Blom <[email protected]>
33
 * @package SimpleSAMLphp
34
 */
35
36
namespace SimpleSAML\Module\ldap\Auth\Process;
37
38
use SimpleSAML\Logger;
39
use SimpleSAML\Module\ldap\Auth\Ldap;
40
use Webmozart\Assert\Assert;
41
42
class AttributeAddFromLDAP extends BaseFilter
43
{
44
    /**
45
     * LDAP attributes to add to the request attributes
46
     *
47
     * @var array
48
     */
49
    protected $search_attributes;
50
51
    /**
52
     * LDAP search filter to use in the LDAP query
53
     *
54
     * @var string
55
     */
56
    protected $search_filter;
57
58
    /**
59
     * What to do with attributes when the target already exists. Either replace, merge or add.
60
     *
61
     * @var string
62
     */
63
    protected $attr_policy;
64
65
66
    /**
67
     * Initialize this filter.
68
     *
69
     * @param array $config Configuration information about this filter.
70
     * @param mixed $reserved For future use.
71
     */
72
    public function __construct(array $config, $reserved)
73
    {
74
        parent::__construct($config, $reserved);
75
76
        // Get filter specific config options
77
        $this->search_attributes = $this->config->getArrayize('attributes', []);
78
        if (empty($this->search_attributes)) {
79
            $new_attribute = $this->config->getString('attribute.new', '');
80
            $this->search_attributes[$new_attribute] = $this->config->getString('search.attribute');
81
        }
82
        $this->search_filter = $this->config->getString('search.filter');
83
84
        // get the attribute policy
85
        $this->attr_policy = $this->config->getString('attribute.policy', 'merge');
86
    }
87
88
89
    /**
90
     * Add attributes from an LDAP server.
91
     *
92
     * @param array &$request The current request
93
     * @return void
94
     */
95
    public function process(array &$request): void
96
    {
97
        Assert::keyExists($request, 'Attributes');
98
99
        $attributes = &$request['Attributes'];
100
101
        // perform a merge on the ldap_search_filter
102
        // loop over the attributes and build the search and replace arrays
103
        $arrSearch = [];
104
        $arrReplace = [];
105
        foreach ($attributes as $attr => $val) {
106
            $arrSearch[] = '%' . $attr . '%';
107
108
            if (is_array($val) && count($val) > 0 && strlen($val[0]) > 0) {
109
                $arrReplace[] = Ldap::escapeFilterValue($val[0]);
110
            } else {
111
                $arrReplace[] = '';
112
            }
113
        }
114
115
        // merge the attributes into the ldap_search_filter
116
        $filter = str_replace($arrSearch, $arrReplace, $this->search_filter);
0 ignored issues
show
Bug introduced by
It seems like $arrReplace can also be of type array<mixed,array|string>; however, parameter $replace of str_replace() does only seem to accept string|string[], maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

116
        $filter = str_replace($arrSearch, /** @scrutinizer ignore-type */ $arrReplace, $this->search_filter);
Loading history...
117
118
        if (strpos($filter, '%') !== false) {
119
            Logger::info(
120
                'AttributeAddFromLDAP: There are non-existing attributes in the search filter. (' .
121
                $this->search_filter . ')'
122
            );
123
            return;
124
        }
125
126
        if (!in_array($this->attr_policy, ['merge', 'replace', 'add'], true)) {
127
            Logger::warning("AttributeAddFromLDAP: 'attribute.policy' must be one of 'merge'," .
128
                "'replace' or 'add'.");
129
            return;
130
        }
131
132
        // getLdap
133
        try {
134
            $ldap = $this->getLdap();
135
        } catch (\Exception $e) {
136
            // Added this warning in case $this->getLdap() fails
137
            Logger::warning("AttributeAddFromLDAP: exception = " . $e);
138
            return;
139
        }
140
        // search for matching entries
141
        try {
142
            $entries = $ldap->searchformultiple(
143
                $this->base_dn,
144
                $filter,
145
                array_values($this->search_attributes),
146
                true,
147
                false
148
            );
149
        } catch (\Exception $e) {
150
            return; // silent fail, error is still logged by LDAP search
151
        }
152
153
        // handle [multiple] values
154
        foreach ($entries as $entry) {
155
            foreach ($this->search_attributes as $target => $name) {
156
                if (is_numeric($target)) {
157
                    $target = $name;
158
                }
159
160
                if (isset($attributes[$target]) && $this->attr_policy === 'replace') {
161
                    unset($attributes[$target]);
162
                }
163
                $name = strtolower($name);
164
                if (isset($entry[$name])) {
165
                    unset($entry[$name]['count']);
166
                    if (isset($attributes[$target])) {
167
                        foreach (array_values($entry[$name]) as $value) {
168
                            if ($this->attr_policy === 'merge') {
169
                                if (!in_array($value, $attributes[$target], true)) {
170
                                    $attributes[$target][] = $value;
171
                                }
172
                            } else {
173
                                $attributes[$target][] = $value;
174
                            }
175
                        }
176
                    } else {
177
                        $attributes[$target] = array_values($entry[$name]);
178
                    }
179
                }
180
            }
181
        }
182
    }
183
}
184