2 # Copyright 2018 Telefonica Investigacion y Desarrollo S.A.U.
6 # Licensed under the Apache License, Version 2.0 (the "License"); you may
7 # not use this file except in compliance with the License. You may obtain
8 # a copy of the License at
10 # http://www.apache.org/licenses/LICENSE-2.0
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
14 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15 # License for the specific language governing permissions and limitations
22 from osmclient
.common
.exceptions
import ClientException
23 from osmclient
.common
.exceptions
import NotFound
29 def __init__(self
, http
=None, client
=None):
32 self
._logger
= logging
.getLogger("osmclient")
33 self
._apiName
= "/admin"
34 self
._apiVersion
= "/v1"
35 self
._apiResource
= "/users"
36 self
._apiBase
= "{}{}{}".format(
37 self
._apiName
, self
._apiVersion
, self
._apiResource
40 def create(self
, name
, user
):
41 """Creates a new OSM user"""
42 self
._logger
.debug("")
43 self
._client
.get_token()
44 if not user
["projects"] or (
45 len(user
["projects"]) == 1 and not user
["projects"][0]
48 elif len(user
["projects"]) == 1:
49 user
["projects"] = user
["projects"][0].split(",")
51 if user
["project_role_mappings"]:
52 project_role_mappings
= []
54 for set_mapping
in user
["project_role_mappings"]:
55 set_mapping_clean
= [m
.strip() for m
in set_mapping
.split(",")]
56 project
, roles
= set_mapping_clean
[0], set_mapping_clean
[1:]
59 mapping
= {"project": project
, "role": role
}
61 if mapping
not in project_role_mappings
:
62 project_role_mappings
.append(mapping
)
63 user
["project_role_mappings"] = project_role_mappings
65 del user
["project_role_mappings"]
67 http_code
, resp
= self
._http
.post_cmd(
68 endpoint
=self
._apiBase
, postfields_dict
=user
, skip_query_admin
=True
70 # print('HTTP CODE: {}'.format(http_code))
71 # print('RESP: {}'.format(resp))
72 # if http_code in (200, 201, 202, 204):
74 resp
= json
.loads(resp
)
75 if not resp
or "id" not in resp
:
76 raise ClientException("unexpected response from server - {}".format(resp
))
82 # msg = json.loads(resp)
85 # raise ClientException("failed to create user {} - {}".format(name, msg))
87 def update(self
, name
, user
, pwd_change
=None):
88 """Updates an existing OSM user identified by name"""
89 self
._logger
.debug("")
91 token_info
= self
._client
.get_token(pwd_change
)
93 token_info
= self
._client
.get_token()
95 myuser
= self
.get(name
)
97 "add_project_role_mappings": [],
98 "remove_project_role_mappings": [],
101 if not user
.get("change_password"):
102 # if password is defined, update the password
103 if user
.get("password"):
104 update_user
["password"] = user
["password"]
105 if user
.get("username"):
106 update_user
["username"] = user
["username"]
108 update_user
["old_password"] = user
["change_password"]
109 update_user
["password"] = user
["new_password"]
111 if user
.get("set-project"):
112 # Remove project and insert project role mapping
113 for set_project
in user
["set-project"]:
114 set_project_clean
= [m
.strip() for m
in set_project
.split(",")]
115 project
, roles
= set_project_clean
[0], set_project_clean
[1:]
117 update_user
["remove_project_role_mappings"].append({"project": project
})
120 mapping
= {"project": project
, "role": role
}
121 update_user
["add_project_role_mappings"].append(mapping
)
123 if user
.get("remove-project"):
124 for remove_project
in user
["remove-project"]:
125 update_user
["remove_project_role_mappings"].append(
126 {"project": remove_project
}
129 if user
.get("add-project-role"):
130 for add_project_role
in user
["add-project-role"]:
131 add_project_role_clean
= [
132 m
.strip() for m
in add_project_role
.split(",")
134 project
, roles
= add_project_role_clean
[0], add_project_role_clean
[1:]
137 mapping
= {"project": project
, "role": role
}
138 update_user
["add_project_role_mappings"].append(mapping
)
140 if user
.get("remove-project-role"):
141 for remove_project_role
in user
["remove-project-role"]:
142 remove_project_role_clean
= [
143 m
.strip() for m
in remove_project_role
.split(",")
146 remove_project_role_clean
[0],
147 remove_project_role_clean
[1:],
151 mapping
= {"project": project
, "role": role
}
152 update_user
["remove_project_role_mappings"].append(mapping
)
154 if user
.get("unlock"):
155 if token_info
.get("admin_show"):
156 update_user
["unlock"] = user
["unlock"]
157 update_user
["system_admin_id"] = token_info
.get("user_id")
159 raise ClientException(
160 "{} does not have privilege to unlock {}".format(
161 token_info
.get("username"), myuser
.get("username")
165 if user
.get("renew"):
166 if token_info
.get("admin_show"):
167 update_user
["renew"] = user
["renew"]
168 update_user
["system_admin_id"] = token_info
.get("user_id")
170 raise ClientException(
171 "{} does not have privilege to renew {}".format(
172 token_info
.get("username"), myuser
.get("username")
176 if not update_user
["remove_project_role_mappings"]:
177 del update_user
["remove_project_role_mappings"]
178 if not update_user
["add_project_role_mappings"]:
179 del update_user
["add_project_role_mappings"]
181 raise ClientException("At least something should be changed.")
183 http_code
, resp
= self
._http
.patch_cmd(
184 endpoint
="{}/{}".format(self
._apiBase
, myuser
["_id"]),
185 postfields_dict
=update_user
,
186 skip_query_admin
=True,
188 # print('HTTP CODE: {}'.format(http_code))
189 # print('RESP: {}'.format(resp))
190 if http_code
in (200, 201, 202):
192 resp
= json
.loads(resp
)
193 if not resp
or "id" not in resp
:
194 raise ClientException(
195 "unexpected response from server - {}".format(resp
)
198 elif http_code
== 204:
204 # msg = json.loads(resp)
207 # raise ClientException("failed to update user {} - {}".format(name, msg))
209 def delete(self
, name
, force
=False):
210 """Deletes an existing OSM user identified by name"""
211 self
._logger
.debug("")
212 self
._client
.get_token()
213 user
= self
.get(name
)
216 querystring
= "?FORCE=True"
217 http_code
, resp
= self
._http
.delete_cmd(
218 "{}/{}{}".format(self
._apiBase
, user
["_id"], querystring
),
219 skip_query_admin
=True,
221 # print('HTTP CODE: {}'.format(http_code))
222 # print('RESP: {}'.format(resp))
224 print("Deletion in progress")
225 elif http_code
== 204:
227 elif resp
and "result" in resp
:
233 # msg = json.loads(resp)
236 raise ClientException("failed to delete user {} - {}".format(name
, msg
))
238 def list(self
, filter=None):
239 """Returns the list of OSM users"""
240 self
._logger
.debug("")
241 response
= self
._client
.get_token()
244 admin_show
= response
.get("admin_show")
248 filter_string
= "?{}".format(filter)
249 _
, resp
= self
._http
.get2_cmd(
250 "{}{}".format(self
._apiBase
, filter_string
), skip_query_admin
=True
252 # print('RESP: {}'.format(resp))
253 if resp
and response
:
254 return json
.loads(resp
), admin_show
256 return json
.loads(resp
)
260 """Returns an OSM user based on name or id"""
261 self
._logger
.debug("")
262 self
._client
.get_token()
263 # keystone with external LDAP contains large ids, not uuid format
264 # utils.validate_uuid4(name) cannot be used
265 user_list
= self
.list()
266 for user
in user_list
:
267 if name
== user
["_id"]:
269 for user
in user_list
:
270 if name
== user
["username"]:
272 raise NotFound("User {} not found".format(name
))