Passed
Pull Request — master (#467)
by Jaspar
10:26
created

UsersMixin.create_user()   B

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