1 # -*- coding: utf-8 -*-
3 # Copyright 2018 Whitestack, LLC
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
9 # http://www.apache.org/licenses/LICENSE-2.0
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
17 # For those usages not covered by the Apache License, Version 2.0 please
18 # contact: esousa@whitestack.com or glavado@whitestack.com
22 Authconn implements an Abstract class for the Auth backend connector
23 plugins with the definition of the methods to be implemented.
26 __author__
= "Eduardo Sousa <esousa@whitestack.com>"
27 __date__
= "$27-jul-2018 23:59:59$"
29 from http
import HTTPStatus
30 from base_topic
import BaseTopic
33 class AuthException(Exception):
35 Authentication error, because token, user password not recognized
37 def __init__(self
, message
, http_code
=HTTPStatus
.UNAUTHORIZED
):
38 super(AuthException
, self
).__init
__(message
)
39 self
.http_code
= http_code
42 class AuthExceptionUnauthorized(AuthException
):
44 Authentication error, because not having rights to make this operation
49 class AuthconnException(Exception):
51 Common and base class Exception for all authconn exceptions.
53 def __init__(self
, message
, http_code
=HTTPStatus
.UNAUTHORIZED
):
54 super(AuthconnException
, self
).__init
__(message
)
55 self
.http_code
= http_code
58 class AuthconnConnectionException(AuthconnException
):
60 Connectivity error with Auth backend.
62 def __init__(self
, message
, http_code
=HTTPStatus
.BAD_GATEWAY
):
63 super(AuthconnConnectionException
, self
).__init
__(message
, http_code
)
66 class AuthconnNotSupportedException(AuthconnException
):
68 The request is not supported by the Auth backend.
70 def __init__(self
, message
, http_code
=HTTPStatus
.NOT_IMPLEMENTED
):
71 super(AuthconnNotSupportedException
, self
).__init
__(message
, http_code
)
74 class AuthconnNotImplementedException(AuthconnException
):
76 The method is not implemented by the Auth backend.
78 def __init__(self
, message
, http_code
=HTTPStatus
.NOT_IMPLEMENTED
):
79 super(AuthconnNotImplementedException
, self
).__init
__(message
, http_code
)
82 class AuthconnOperationException(AuthconnException
):
84 The operation executed failed.
86 def __init__(self
, message
, http_code
=HTTPStatus
.INTERNAL_SERVER_ERROR
):
87 super(AuthconnOperationException
, self
).__init
__(message
, http_code
)
90 class AuthconnNotFoundException(AuthconnException
):
92 The operation executed failed because element not found.
94 def __init__(self
, message
, http_code
=HTTPStatus
.NOT_FOUND
):
95 super().__init
__(message
, http_code
)
98 class AuthconnConflictException(AuthconnException
):
100 The operation has conflicts.
102 def __init__(self
, message
, http_code
=HTTPStatus
.CONFLICT
):
103 super().__init
__(message
, http_code
)
108 Abstract base class for all the Auth backend connector plugins.
109 Each Auth backend connector plugin must be a subclass of
112 def __init__(self
, config
, db
, token_cache
):
114 Constructor of the Authconn class.
118 :param config: configuration dictionary containing all the
119 necessary configuration parameters.
123 def authenticate(self
, user
, password
, project
=None, token_info
=None):
125 Authenticate a user using username/password or token_info, plus project
126 :param user: user: name, id or None
127 :param password: password or None
128 :param project: name, id, or None. If None first found project will be used to get an scope token
129 :param token_info: previous token_info to obtain authorization
130 :return: the scoped token info or raises an exception. The token is a dictionary with:
131 _id: token string id,
133 project_id: scoped_token project_id,
134 project_name: scoped_token project_name,
135 expires: epoch time when it expires,
138 raise AuthconnNotImplementedException("Should have implemented this")
140 def validate_token(self
, token
):
142 Check if the token is valid.
144 :param token: token to validate
145 :return: dictionary with information associated with the token. If the
146 token is not valid, returns None.
148 raise AuthconnNotImplementedException("Should have implemented this")
150 def revoke_token(self
, token
):
154 :param token: token to be revoked
156 raise AuthconnNotImplementedException("Should have implemented this")
158 def create_user(self
, user_info
):
162 :param user_info: full user info.
163 :raises AuthconnOperationException: if user creation failed.
165 raise AuthconnNotImplementedException("Should have implemented this")
167 def update_user(self
, user_info
):
169 Change the user name and/or password.
171 :param user_info: user info modifications
172 :raises AuthconnNotImplementedException: if function not implemented
174 raise AuthconnNotImplementedException("Should have implemented this")
176 def delete_user(self
, user_id
):
180 :param user_id: user identifier.
181 :raises AuthconnOperationException: if user deletion failed.
183 raise AuthconnNotImplementedException("Should have implemented this")
185 def get_user_list(self
, filter_q
=None):
189 :param filter_q: dictionary to filter user list by name (username is also admited) and/or _id
190 :return: returns a list of users.
193 def get_user(self
, id, fail
=True):
194 filt
= {BaseTopic
.id_field("users", id): id}
195 users
= self
.get_user_list(filt
)
198 raise AuthconnNotFoundException("User with {} not found".format(filt
), http_code
=HTTPStatus
.NOT_FOUND
)
203 def create_role(self
, role_info
):
207 :param role_info: full role info.
208 :raises AuthconnOperationException: if role creation failed.
210 raise AuthconnNotImplementedException("Should have implemented this")
212 def delete_role(self
, role_id
):
216 :param role_id: role identifier.
217 :raises AuthconnOperationException: if user deletion failed.
219 raise AuthconnNotImplementedException("Should have implemented this")
221 def get_role_list(self
, filter_q
=None):
225 :param filter_q: dictionary to filter role list by _id and/or name.
226 :return: list of roles
228 raise AuthconnNotImplementedException("Should have implemented this")
230 def get_role(self
, id, fail
=True):
231 filt
= {BaseTopic
.id_field("roles", id): id}
232 roles
= self
.get_role_list(filt
)
235 raise AuthconnNotFoundException("Role with {} not found".format(filt
))
240 def update_role(self
, role_info
):
242 Change the information of a role
243 :param role_info: full role info
246 raise AuthconnNotImplementedException("Should have implemented this")
248 def create_project(self
, project_info
):
252 :param project_info: full project info.
253 :return: the internal id of the created project
254 :raises AuthconnOperationException: if project creation failed.
256 raise AuthconnNotImplementedException("Should have implemented this")
258 def delete_project(self
, project_id
):
262 :param project_id: project identifier.
263 :raises AuthconnOperationException: if project deletion failed.
265 raise AuthconnNotImplementedException("Should have implemented this")
267 def get_project_list(self
, filter_q
=None):
269 Get all the projects.
271 :param filter_q: dictionary to filter project list, by "name" and/or "_id"
272 :return: list of projects
274 raise AuthconnNotImplementedException("Should have implemented this")
276 def get_project(self
, id, fail
=True):
277 filt
= {BaseTopic
.id_field("projects", id): id}
278 projs
= self
.get_project_list(filt
)
281 raise AuthconnNotFoundException("project with {} not found".format(filt
))
286 def update_project(self
, project_id
, project_info
):
288 Change the information of a project
289 :param project_id: project to be changed
290 :param project_info: full project info
293 raise AuthconnNotImplementedException("Should have implemented this")