CI: Use latest actions and reusable workflows
[releng/lftools.git] / lftools / lfidapi.py
1 # SPDX-License-Identifier: EPL-1.0
2 ##############################################################################
3 # Copyright (c) 2018 The Linux Foundation and others.
4 #
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Eclipse Public License v1.0
7 # which accompanies this distribution, and is available at
8 # http://www.eclipse.org/legal/epl-v10.html
9 ##############################################################################
10 """Use the LFIDAPI to add, remove and list members as well as create groups."""
11
12 import json
13 import logging
14 import sys
15
16 import requests
17 import yaml
18 from email_validator import validate_email
19 from six.moves import urllib
20
21 from lftools.github_helper import helper_list, helper_user_github
22 from lftools.oauth2_helper import oauth_helper
23
24 log = logging.getLogger(__name__)
25
26 PARSE = urllib.parse.urljoin
27
28
29 def check_response_code(response):
30     """Response Code Helper function."""
31     if response.status_code != 200:
32         raise requests.HTTPError(
33             "Authorization failed with the following " "error:\n{}: {}".format(response.status_code, response.text)
34         )
35
36
37 def helper_check_group_exists(group):
38     """Check group exists."""
39     access_token, url = oauth_helper()
40     url = PARSE(url, group)
41     headers = {"Authorization": "Bearer " + access_token}
42     response = requests.get(url, headers=headers)
43     status_code = response.status_code
44     return status_code
45
46
47 def helper_search_members(group):
48     """List members of a group."""
49     response_code = helper_check_group_exists(group)
50     if response_code != 200:
51         log.error("Code: {} Group {} does not exists exiting...".format(response_code, group))
52         sys.exit(1)
53     else:
54         access_token, url = oauth_helper()
55         url = PARSE(url, group)
56         headers = {"Authorization": "Bearer " + access_token}
57         response = requests.get(url, headers=headers)
58         try:
59             check_response_code(response)
60         except requests.HTTPError as e:
61             log.error(e)
62             exit(1)
63         result = response.json()
64         members = result["members"]
65         log.debug(json.dumps(members, indent=4, sort_keys=True))
66         return members
67
68
69 def helper_user(user, group, delete):
70     """Add and remove users from groups."""
71     access_token, url = oauth_helper()
72     url = PARSE(url, group)
73     headers = {"Authorization": "Bearer " + access_token}
74     data = {"username": user}
75     if delete:
76         log.info("Deleting %s from %s" % (user, group))
77         response = requests.delete(url, json=data, headers=headers)
78     else:
79         log.info("Adding %s to %s" % (user, group))
80         response = requests.put(url, json=data, headers=headers)
81     try:
82         check_response_code(response)
83     except requests.HTTPError as e:
84         log.error(e)
85         exit(1)
86     result = response.json()
87     log.debug(json.dumps(result, indent=4, sort_keys=True))
88
89
90 def helper_invite(email, group):
91     """Email invitation to join group."""
92     access_token, url = oauth_helper()
93     prejoin = group + "/invite"
94     url = PARSE(url, prejoin)
95     headers = {"Authorization": "Bearer " + access_token}
96     data = {"mail": email}
97     log.info("Validating email %s" % email)
98     if validate_email(email):
99         log.info("Inviting %s to join %s" % (email, group))
100         response = requests.post(url, json=data, headers=headers)
101         try:
102             check_response_code(response)
103         except requests.HTTPError as e:
104             log.error(e)
105             exit(1)
106         result = response.json()
107         log.debug(json.dumps(result, indent=4, sort_keys=True))
108     else:
109         log.error("Email '%s' is not valid, not inviting to %s" % (email, group))
110
111
112 def helper_create_group(group):
113     """Create group."""
114     response_code = helper_check_group_exists(group)
115     if response_code == 200:
116         log.error("Group %s already exists. Exiting..." % group)
117     else:
118         access_token, url = oauth_helper()
119         url = "{}/".format(url)
120         headers = {"Authorization": "Bearer " + access_token}
121         data = {"title": group, "type": "group"}
122         log.debug(data)
123         log.info("Creating group %s" % group)
124         response = requests.post(url, json=data, headers=headers)
125         try:
126             check_response_code(response)
127         except requests.HTTPError as e:
128             log.error(e)
129             exit(1)
130         result = response.json()
131         log.debug(json.dumps(result, indent=4, sort_keys=True))
132
133
134 def helper_match_ldap_to_info(info_file, group, githuborg, noop):
135     """Helper matches ldap or github group to users in an info file.
136
137     Used in automation.
138     """
139     with open(info_file) as file:
140         try:
141             info_data = yaml.safe_load(file)
142         except yaml.YAMLError as exc:
143             print(exc)
144     id = "id"
145     if githuborg:
146         id = "github_id"
147         ldap_data = helper_list(
148             ctx=False,
149             organization=githuborg,
150             repos=False,
151             audit=False,
152             full=False,
153             teams=False,
154             repofeatures=False,
155             team=group,
156         )
157     else:
158         ldap_data = helper_search_members(group)
159
160     committer_info = info_data["committers"]
161
162     info_committers = []
163     for count, item in enumerate(committer_info):
164         committer = committer_info[count][id]
165         info_committers.append(committer)
166
167     ldap_committers = []
168     if githuborg:
169         for x in ldap_data:
170             committer = x
171             ldap_committers.append(committer)
172
173     else:
174         for count, item in enumerate(ldap_data):
175             committer = ldap_data[count]["username"]
176             ldap_committers.append(committer)
177
178     all_users = ldap_committers + info_committers
179
180     if not githuborg:
181         all_users.remove("lfservices_releng")
182
183     log.info("All users in org group")
184     all_users = sorted(set(all_users))
185     for x in all_users:
186         log.info(x)
187
188     for user in all_users:
189         removed_by_patch = [item for item in ldap_committers if item not in info_committers]
190         if user in removed_by_patch:
191             log.info("%s found in group %s " % (user, group))
192             if noop is False:
193                 log.info("Removing user %s from group %s" % (user, group))
194                 if githuborg:
195                     helper_user_github(
196                         ctx=False, organization=githuborg, user=user, team=group, delete=True, admin=False
197                     )
198                 else:
199                     helper_user(user, group, "--delete")
200
201         added_by_patch = [item for item in info_committers if item not in ldap_committers]
202         if user in added_by_patch:
203             log.info("%s not found in group %s" % (user, group))
204             if noop is False:
205                 log.info("Adding user %s to group %s" % (user, group))
206                 if githuborg:
207                     helper_user_github(
208                         ctx=False, organization=githuborg, user=user, team=group, delete=False, admin=False
209                     )
210
211                 else:
212                     helper_user(user, group, "")