Completed
Push — master ( 1fe696...91c058 )
by Damien
04:44
created

UserGroups::syncByAssertion()   C

Complexity

Conditions 9
Paths 18

Size

Total Lines 92

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
dl 0
loc 92
ccs 0
cts 37
cp 0
rs 6.6189
c 0
b 0
f 0
cc 9
nc 18
nop 2
crap 90

How to fix   Long Method   

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
 * @copyright  Copyright (c) Flipbox Digital Limited
5
 */
6
7
namespace flipbox\saml\sp\services\login;
8
9
use craft\elements\User as UserElement;
10
use craft\helpers\StringHelper;
11
use craft\models\UserGroup;
12
use flipbox\saml\sp\Saml;
13
use SAML2\Assertion;
14
use yii\base\UserException;
15
16
/**
17
 * Class UserGroups
18
 * @package flipbox\saml\sp\services
19
 */
20
class UserGroups
21
{
22
23
    /**
24
     * @param string $groupName
25
     * @return UserGroup
26
     * @throws UserException
27
     * @throws \craft\errors\WrongEditionException
28
     */
29
    protected function findOrCreate($groupName): UserGroup
30
    {
31
32
        $groupHandle = StringHelper::camelCase($groupName);
33
34
        if (! $userGroup = \Craft::$app->getUserGroups()->getGroupByHandle($groupHandle)) {
35
            if (! \Craft::$app->getUserGroups()->saveGroup(
36
                $userGroup = new UserGroup(
37
                    [
38
                        'name' => $groupName,
39
                        'handle' => $groupHandle,
40
                    ]
41
                )
42
            )
43
            ) {
44
                throw new UserException("Error saving new group {$groupHandle}");
45
            }
46
        }
47
48
        return $userGroup;
49
    }
50
51
52
    /**
53
     * @param UserElement $user
54
     * @param Assertion $assertion
55
     * @return bool
56
     * @throws UserException
57
     * @throws \craft\errors\WrongEditionException
58
     */
59
    public function syncByAssertion(UserElement $user, Assertion $assertion)
60
    {
61
        /**
62
         * Nothing to do, move on
63
         */
64
        if (false === Saml::getInstance()->getSettings()->syncGroups) {
65
            return true;
66
        }
67
68
        $groupNames = Saml::getInstance()->getSettings()->groupAttributeNames;
69
        $groups = [];
70
        /**
71
         * Make sure there is an attribute statement
72
         */
73
        if (! $assertion->getAttributes()) {
74
            Saml::debug(
75
                'No attribute statement found, moving on.'
76
            );
77
            return true;
78
        }
79
80
        foreach ($assertion->getAttributes() as $attributeName => $attributeValue) {
81
            Saml::debug(
82
                sprintf(
83
                    'Is attribute group? "%s" in %s',
84
                    $attributeName,
85
                    json_encode($groupNames)
86
                )
87
            );
88
            /**
89
             * Is there a group name match?
90
             * Match the attribute name to the specified name in the plugin settings
91
             */
92
            if (in_array($attributeName, $groupNames)) {
93
                /**
94
                 * Loop thru all of the attributes values because they could have multiple values.
95
                 * Example XML:
96
                 * <saml2:Attribute Name="groups" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
97
                 *   <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
98
                 *           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
99
                 *           craft_admin
100
                 *           </saml2:AttributeValue>
101
                 *   <saml2:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
102
                 *           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
103
                 *           craft_member
104
                 *           </saml2:AttributeValue>
105
                 * </saml2:Attribute>
106
                 */
107
                if (! is_array($attributeValue)) {
108
                    $attributeValue = [$attributeValue];
109
                }
110
111
                foreach ($attributeValue as $values) {
112
                    if ($group = $this->findOrCreate($values)) {
113
                        Saml::debug(
114
                            sprintf(
115
                                'Assigning group: %s',
116
                                $group->name
117
                            )
118
                        );
119
                        $groups[] = $group->id;
120
                    }
121
                }
122
            }
123
        }
124
        /**
125
         * just return if this is empty
126
         */
127
        if (empty($groups)) {
128
            return true;
129
        }
130
131
        /**
132
         * Get existing groups
133
         */
134
        $existingGroupIds = array_map(
135
            function ($group) {
136
                return (int)$group->id;
137
            },
138
            $user->getGroups()
139
        );
140
141
        return \Craft::$app->getUsers()->assignUserToGroups(
142
            $user->id,
143
            array_unique(
144
                array_merge(
145
                    $existingGroupIds,
146
                    $groups
147
                )
148
            )
149
        );
150
    }
151
152
    /**
153
     * @param UserElement $user
154
     * @return bool|null
155
     */
156
    public function assignDefaultGroups(\craft\elements\User $user)
157
    {
158
        $groups = array_merge(
159
            $user->getGroups(),
160
            $newGroups = $this->getDefaultGroups()
161
        );
162
163
        /**
164
         * if it's not empty add the groups
165
         */
166
        if (! empty($newGroups)) {
167
            $groupIds = array_map(
168
                function ($group) {
169
                    return (int)$group->id;
170
                },
171
                $groups
172
            );
173
174
            if (\Craft::$app->getUsers()->assignUserToGroups($user->id, array_unique($groupIds))) {
175
                $user->setGroups($groups);
176
            }
177
        }
178
179
        return null;
180
    }
181
182
    /**
183
     * @return array
184
     */
185
    public function getDefaultGroups()
186
    {
187
        $groups = [];
188
        foreach (Saml::getInstance()->getSettings()->defaultGroupAssignments as $groupId) {
189
            $groups[$groupId] = \Craft::$app->getUserGroups()->getGroupById($groupId);
190
        }
191
192
        return $groups;
193
    }
194
}
195