Completed
Push — master ( 486e1a...9be8a7 )
by Jaspar
02:33 queued 36s
created

gvm.protocols.gmpv208.entities.users   A

Complexity

Total Complexity 36

Size/Duplication

Total Lines 305
Duplicated Lines 31.8 %

Importance

Changes 0
Metric Value
eloc 141
dl 97
loc 305
rs 9.52
c 0
b 0
f 0
wmc 36

6 Methods

Rating   Name   Duplication   Size   Complexity  
F UsersMixin.modify_user() 97 97 14
B UsersMixin.create_user() 0 57 7
B UsersMixin.delete_user() 0 39 7
A UsersMixin.get_users() 0 17 1
A UsersMixin.clone_user() 0 17 2
A UsersMixin.get_user() 0 18 2

1 Function

Rating   Name   Duplication   Size   Complexity  
A get_user_auth_type_from_string() 0 14 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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