UsersMixin.create_user()   B
last analyzed

Complexity

Conditions 7

Size

Total Lines 57
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 31
nop 9
dl 0
loc 57
rs 7.736
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

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:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
# -*- coding: utf-8 -*-
2
# Copyright (C) 2021 Greenbone Networks GmbH
3
#
4
# SPDX-License-Identifier: GPL-3.0-or-later
5
#
6
# This program is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
19
20
from enum import Enum
21
from typing import Any, List, Optional
22
23
from gvm.errors import RequiredArgument, InvalidArgument
24
from gvm.utils import add_filter, to_comma_list, to_bool
25
from gvm.xml import XmlCommand
26
27
28
class UserAuthType(Enum):
29
    """Enum for Sources allowed for authentication for the user"""
30
31
    FILE = 'file'
32
    LDAP_CONNECT = 'ldap_connect'
33
    RADIUS_CONNECT = 'radius_connect'
34
35
36
def get_user_auth_type_from_string(
37
    user_auth_type: Optional[str],
38
) -> Optional[UserAuthType]:
39
    """Convert a user auth type string into a UserAuthType instance"""
40
    if not user_auth_type:
41
        return None
42
43
    try:
44
        return UserAuthType[user_auth_type.upper()]
45
    except KeyError:
46
        raise InvalidArgument(
47
            argument='user_auth_type',
48
            function=get_user_auth_type_from_string.__name__,
49
        ) from None
50
51
52
class UsersMixin:
53
    def clone_user(self, user_id: str) -> Any:
54
        """Clone an existing user
55
56
        Arguments:
57
            user_id: UUID of existing user to clone from
58
59
        Returns:
60
            The response. See :py:meth:`send_command` for details.
61
        """
62
        if not user_id:
63
            raise RequiredArgument(
64
                function=self.clone_user.__name__, argument='user_id'
65
            )
66
67
        cmd = XmlCommand("create_user")
68
        cmd.add_element("copy", user_id)
69
        return self._send_xml_command(cmd)
70
71
    def create_user(
72
        self,
73
        name: str,
74
        *,
75
        password: Optional[str] = None,
76
        hosts: Optional[List[str]] = None,
77
        hosts_allow: Optional[bool] = False,
78
        ifaces: Optional[List[str]] = None,
79
        ifaces_allow: Optional[bool] = False,
80
        role_ids: Optional[List[str]] = None,
81
    ) -> Any:
82
        """Create a new user
83
84
        Arguments:
85
            name: Name of the user
86
            password: Password of the user
87
            hosts: A list of host addresses (IPs, DNS names)
88
            hosts_allow: If True allow only access to passed hosts otherwise
89
                deny access. Default is False for deny hosts.
90
            ifaces: A list of interface names
91
            ifaces_allow: If True allow only access to passed interfaces
92
                otherwise deny access. Default is False for deny interfaces.
93
            role_ids: A list of role UUIDs for the user
94
95
        Returns:
96
            The response. See :py:meth:`send_command` for details.
97
        """
98
        if not name:
99
            raise RequiredArgument(
100
                function=self.create_user.__name__, argument='name'
101
            )
102
103
        cmd = XmlCommand("create_user")
104
        cmd.add_element("name", name)
105
106
        if password:
107
            cmd.add_element("password", password)
108
109
        if hosts:
110
            cmd.add_element(
111
                "hosts",
112
                to_comma_list(hosts),
113
                attrs={"allow": to_bool(hosts_allow)},
114
            )
115
116
        if ifaces:
117
            cmd.add_element(
118
                "ifaces",
119
                to_comma_list(ifaces),
120
                attrs={"allow": to_bool(ifaces_allow)},
121
            )
122
123
        if role_ids:
124
            for role in role_ids:
125
                cmd.add_element("role", attrs={"id": role})
126
127
        return self._send_xml_command(cmd)
128
129
    def delete_user(
130
        self,
131
        user_id: str = None,
132
        *,
133
        name: Optional[str] = None,
134
        inheritor_id: Optional[str] = None,
135
        inheritor_name: Optional[str] = None,
136
    ) -> Any:
137
        """Deletes an existing user
138
139
        Either user_id or name must be passed.
140
141
        Arguments:
142
            user_id: UUID of the task to be deleted.
143
            name: The name of the user to be deleted.
144
            inheritor_id: The ID of the inheriting user or "self". Overrides
145
                inheritor_name.
146
            inheritor_name: The name of the inheriting user.
147
148
        """
149
        if not user_id and not name:
150
            raise RequiredArgument(
151
                function=self.delete_user.__name__, argument='user_id or name'
152
            )
153
154
        cmd = XmlCommand("delete_user")
155
156
        if user_id:
157
            cmd.set_attribute("user_id", user_id)
158
159
        if name:
160
            cmd.set_attribute("name", name)
161
162
        if inheritor_id:
163
            cmd.set_attribute("inheritor_id", inheritor_id)
164
        if inheritor_name:
165
            cmd.set_attribute("inheritor_name", inheritor_name)
166
167
        return self._send_xml_command(cmd)
168
169
    def get_users(
170
        self,
171
        *,
172
        filter_string: Optional[str] = None,
173
        filter_id: Optional[str] = None,
174
    ) -> Any:
175
        """Request a list of users
176
177
        Arguments:
178
            filter_string: Filter term to use for the query
179
            filter_id: UUID of an existing filter to use for the query
180
181
        Returns:
182
            The response. See :py:meth:`send_command` for details.
183
        """
184
        cmd = XmlCommand("get_users")
185
186
        add_filter(cmd, filter_string, filter_id)
187
188
        return self._send_xml_command(cmd)
189
190
    def get_user(self, user_id: str) -> Any:
191
        """Request a single user
192
193
        Arguments:
194
            user_id: UUID of an existing user
195
196
        Returns:
197
            The response. See :py:meth:`send_command` for details.
198
        """
199
        cmd = XmlCommand("get_users")
200
201
        if not user_id:
202
            raise RequiredArgument(
203
                function=self.get_user.__name__, argument='user_id'
204
            )
205
206
        cmd.set_attribute("user_id", user_id)
207
        return self._send_xml_command(cmd)
208
209
    def modify_user(
210
        self,
211
        user_id: str = None,
212
        name: str = None,
213
        *,
214
        new_name: Optional[str] = None,
215
        comment: Optional[str] = None,
216
        password: Optional[str] = None,
217
        auth_source: Optional[UserAuthType] = None,
218
        role_ids: Optional[List[str]] = None,
219
        hosts: Optional[List[str]] = None,
220
        hosts_allow: Optional[bool] = False,
221
        ifaces: Optional[List[str]] = None,
222
        ifaces_allow: Optional[bool] = False,
223
        group_ids: Optional[List[str]] = None,
224
    ) -> Any:
225
        """Modifies an existing user.
226
227
        Most of the fields need to be supplied
228
        for changing a single field even if no change is wanted for those.
229
        Else empty values are inserted for the missing fields instead.
230
231
        Arguments:
232
            user_id: UUID of the user to be modified. Overrides name element
233
                argument.
234
            name: The name of the user to be modified. Either user_id or name
235
                must be passed.
236
            new_name: The new name for the user.
237
            comment: Comment on the user.
238
            password: The password for the user.
239
            auth_source: Source allowed for authentication for this user.
240
            roles_id: List of roles UUIDs for the user.
241
            hosts: User access rules: List of hosts.
242
            hosts_allow: Defines how the hosts list is to be interpreted.
243
                If False (default) the list is treated as a deny list.
244
                All hosts are allowed by default except those provided by
245
                the hosts parameter. If True the list is treated as a
246
                allow list. All hosts are denied by default except those
247
                provided by the hosts parameter.
248
            ifaces: User access rules: List of ifaces.
249
            ifaces_allow: Defines how the ifaces list is to be interpreted.
250
                If False (default) the list is treated as a deny list.
251
                All ifaces are allowed by default except those provided by
252
                the ifaces parameter. If True the list is treated as a
253
                allow list. All ifaces are denied by default except those
254
                provided by the ifaces parameter.
255
            group_ids: List of group UUIDs for the user.
256
257
        Returns:
258
            The response. See :py:meth:`send_command` for details.
259
        """
260
        if not user_id and not name:
261
            raise RequiredArgument(
262
                function=self.modify_user.__name__, argument='user_id or name'
263
            )
264
265
        cmd = XmlCommand("modify_user")
266
267
        if user_id:
268
            cmd.set_attribute("user_id", user_id)
269
        else:
270
            cmd.add_element("name", name)
271
272
        if new_name:
273
            cmd.add_element("new_name", new_name)
274
275
        if role_ids:
276
            for role in role_ids:
277
                cmd.add_element("role", attrs={"id": role})
278
279
        if hosts:
280
            cmd.add_element(
281
                "hosts",
282
                to_comma_list(hosts),
283
                attrs={"allow": to_bool(hosts_allow)},
284
            )
285
286
        if ifaces:
287
            cmd.add_element(
288
                "ifaces",
289
                to_comma_list(ifaces),
290
                attrs={"allow": to_bool(ifaces_allow)},
291
            )
292
293
        if comment:
294
            cmd.add_element("comment", comment)
295
296
        if password:
297
            cmd.add_element("password", password)
298
299
        if auth_source:
300
            _xmlauthsrc = cmd.add_element("sources")
301
            _xmlauthsrc.add_element("source", auth_source.value)
302
303
        if group_ids:
304
            _xmlgroups = cmd.add_element("groups")
305
            for group_id in group_ids:
306
                _xmlgroups.add_element("group", attrs={"id": group_id})
307
308
        return self._send_xml_command(cmd)
309