Tests for NBI Quotas
[osm/NBI.git] / osm_nbi / authconn.py
1 # -*- coding: utf-8 -*-
2
3 # Copyright 2018 Whitestack, LLC
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); you may
6 # not use this file except in compliance with the License. You may obtain
7 # a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 # License for the specific language governing permissions and limitations
15 # under the License.
16 #
17 # For those usages not covered by the Apache License, Version 2.0 please
18 # contact: esousa@whitestack.com or glavado@whitestack.com
19 ##
20
21 """
22 Authconn implements an Abstract class for the Auth backend connector
23 plugins with the definition of the methods to be implemented.
24 """
25
26 __author__ = "Eduardo Sousa <esousa@whitestack.com>, " \
27 "Pedro de la Cruz Ramos <pdelacruzramos@altran.com>"
28 __date__ = "$27-jul-2018 23:59:59$"
29
30 from http import HTTPStatus
31 from osm_nbi.base_topic import BaseTopic
32
33
34 class AuthException(Exception):
35 """
36 Authentication error, because token, user password not recognized
37 """
38 def __init__(self, message, http_code=HTTPStatus.UNAUTHORIZED):
39 super(AuthException, self).__init__(message)
40 self.http_code = http_code
41
42
43 class AuthExceptionUnauthorized(AuthException):
44 """
45 Authentication error, because not having rights to make this operation
46 """
47 pass
48
49
50 class AuthconnException(Exception):
51 """
52 Common and base class Exception for all authconn exceptions.
53 """
54 def __init__(self, message, http_code=HTTPStatus.UNAUTHORIZED):
55 super(AuthconnException, self).__init__(message)
56 self.http_code = http_code
57
58
59 class AuthconnConnectionException(AuthconnException):
60 """
61 Connectivity error with Auth backend.
62 """
63 def __init__(self, message, http_code=HTTPStatus.BAD_GATEWAY):
64 super(AuthconnConnectionException, self).__init__(message, http_code)
65
66
67 class AuthconnNotSupportedException(AuthconnException):
68 """
69 The request is not supported by the Auth backend.
70 """
71 def __init__(self, message, http_code=HTTPStatus.NOT_IMPLEMENTED):
72 super(AuthconnNotSupportedException, self).__init__(message, http_code)
73
74
75 class AuthconnNotImplementedException(AuthconnException):
76 """
77 The method is not implemented by the Auth backend.
78 """
79 def __init__(self, message, http_code=HTTPStatus.NOT_IMPLEMENTED):
80 super(AuthconnNotImplementedException, self).__init__(message, http_code)
81
82
83 class AuthconnOperationException(AuthconnException):
84 """
85 The operation executed failed.
86 """
87 def __init__(self, message, http_code=HTTPStatus.INTERNAL_SERVER_ERROR):
88 super(AuthconnOperationException, self).__init__(message, http_code)
89
90
91 class AuthconnNotFoundException(AuthconnException):
92 """
93 The operation executed failed because element not found.
94 """
95 def __init__(self, message, http_code=HTTPStatus.NOT_FOUND):
96 super().__init__(message, http_code)
97
98
99 class AuthconnConflictException(AuthconnException):
100 """
101 The operation has conflicts.
102 """
103 def __init__(self, message, http_code=HTTPStatus.CONFLICT):
104 super().__init__(message, http_code)
105
106
107 class Authconn:
108 """
109 Abstract base class for all the Auth backend connector plugins.
110 Each Auth backend connector plugin must be a subclass of
111 Authconn class.
112 """
113 def __init__(self, config, db, token_cache):
114 """
115 Constructor of the Authconn class.
116
117 Note: each subclass
118
119 :param config: configuration dictionary containing all the
120 necessary configuration parameters.
121 """
122 self.config = config
123
124 def authenticate(self, user, password, project=None, token_info=None):
125 """
126 Authenticate a user using username/password or token_info, plus project
127 :param user: user: name, id or None
128 :param password: password or None
129 :param project: name, id, or None. If None first found project will be used to get an scope token
130 :param token_info: previous token_info to obtain authorization
131 :return: the scoped token info or raises an exception. The token is a dictionary with:
132 _id: token string id,
133 username: username,
134 project_id: scoped_token project_id,
135 project_name: scoped_token project_name,
136 expires: epoch time when it expires,
137
138 """
139 raise AuthconnNotImplementedException("Should have implemented this")
140
141 def validate_token(self, token):
142 """
143 Check if the token is valid.
144
145 :param token: token to validate
146 :return: dictionary with information associated with the token. If the
147 token is not valid, returns None.
148 """
149 raise AuthconnNotImplementedException("Should have implemented this")
150
151 def revoke_token(self, token):
152 """
153 Invalidate a token.
154
155 :param token: token to be revoked
156 """
157 raise AuthconnNotImplementedException("Should have implemented this")
158
159 def create_user(self, user_info):
160 """
161 Create a user.
162
163 :param user_info: full user info.
164 :raises AuthconnOperationException: if user creation failed.
165 """
166 raise AuthconnNotImplementedException("Should have implemented this")
167
168 def update_user(self, user_info):
169 """
170 Change the user name and/or password.
171
172 :param user_info: user info modifications
173 :raises AuthconnNotImplementedException: if function not implemented
174 """
175 raise AuthconnNotImplementedException("Should have implemented this")
176
177 def delete_user(self, user_id):
178 """
179 Delete user.
180
181 :param user_id: user identifier.
182 :raises AuthconnOperationException: if user deletion failed.
183 """
184 raise AuthconnNotImplementedException("Should have implemented this")
185
186 def get_user_list(self, filter_q=None):
187 """
188 Get user list.
189
190 :param filter_q: dictionary to filter user list by name (username is also admited) and/or _id
191 :return: returns a list of users.
192 """
193
194 def get_user(self, _id, fail=True):
195 """
196 Get one user
197 :param _id: id or name
198 :param fail: True to raise exception on not found. False to return None on not found
199 :return: dictionary with the user information
200 """
201 filt = {BaseTopic.id_field("users", _id): _id}
202 users = self.get_user_list(filt)
203 if not users:
204 if fail:
205 raise AuthconnNotFoundException("User with {} not found".format(filt), http_code=HTTPStatus.NOT_FOUND)
206 else:
207 return None
208 return users[0]
209
210 def create_role(self, role_info):
211 """
212 Create a role.
213
214 :param role_info: full role info.
215 :raises AuthconnOperationException: if role creation failed.
216 """
217 raise AuthconnNotImplementedException("Should have implemented this")
218
219 def delete_role(self, role_id):
220 """
221 Delete a role.
222
223 :param role_id: role identifier.
224 :raises AuthconnOperationException: if user deletion failed.
225 """
226 raise AuthconnNotImplementedException("Should have implemented this")
227
228 def get_role_list(self, filter_q=None):
229 """
230 Get all the roles.
231
232 :param filter_q: dictionary to filter role list by _id and/or name.
233 :return: list of roles
234 """
235 raise AuthconnNotImplementedException("Should have implemented this")
236
237 def get_role(self, _id, fail=True):
238 """
239 Get one role
240 :param _id: id or name
241 :param fail: True to raise exception on not found. False to return None on not found
242 :return: dictionary with the role information
243 """
244 filt = {BaseTopic.id_field("roles", _id): _id}
245 roles = self.get_role_list(filt)
246 if not roles:
247 if fail:
248 raise AuthconnNotFoundException("Role with {} not found".format(filt))
249 else:
250 return None
251 return roles[0]
252
253 def update_role(self, role_info):
254 """
255 Change the information of a role
256 :param role_info: full role info
257 :return: None
258 """
259 raise AuthconnNotImplementedException("Should have implemented this")
260
261 def create_project(self, project_info):
262 """
263 Create a project.
264
265 :param project_info: full project info.
266 :return: the internal id of the created project
267 :raises AuthconnOperationException: if project creation failed.
268 """
269 raise AuthconnNotImplementedException("Should have implemented this")
270
271 def delete_project(self, project_id):
272 """
273 Delete a project.
274
275 :param project_id: project identifier.
276 :raises AuthconnOperationException: if project deletion failed.
277 """
278 raise AuthconnNotImplementedException("Should have implemented this")
279
280 def get_project_list(self, filter_q=None):
281 """
282 Get all the projects.
283
284 :param filter_q: dictionary to filter project list, by "name" and/or "_id"
285 :return: list of projects
286 """
287 raise AuthconnNotImplementedException("Should have implemented this")
288
289 def get_project(self, _id, fail=True):
290 """
291 Get one project
292 :param _id: id or name
293 :param fail: True to raise exception on not found. False to return None on not found
294 :return: dictionary with the project information
295 """
296 filt = {BaseTopic.id_field("projects", _id): _id}
297 projs = self.get_project_list(filt)
298 if not projs:
299 if fail:
300 raise AuthconnNotFoundException("project with {} not found".format(filt))
301 else:
302 return None
303 return projs[0]
304
305 def update_project(self, project_id, project_info):
306 """
307 Change the information of a project
308 :param project_id: project to be changed
309 :param project_info: full project info
310 :return: None
311 """
312 raise AuthconnNotImplementedException("Should have implemented this")