Fix Bug 774 - NBI+Keystone: Trying to obtain a token with user+password+project gives...
[osm/NBI.git] / osm_nbi / authconn.py
index 4d28bf8..140e024 100644 (file)
@@ -1,5 +1,23 @@
 # -*- coding: utf-8 -*-
 
 # -*- coding: utf-8 -*-
 
+# Copyright 2018 Whitestack, LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#         http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+# For those usages not covered by the Apache License, Version 2.0 please
+# contact: esousa@whitestack.com or glavado@whitestack.com
+##
+
 """
 Authconn implements an Abstract class for the Auth backend connector
 plugins with the definition of the methods to be implemented.
 """
 Authconn implements an Abstract class for the Auth backend connector
 plugins with the definition of the methods to be implemented.
@@ -13,11 +31,18 @@ from http import HTTPStatus
 
 class AuthException(Exception):
     """
 
 class AuthException(Exception):
     """
-    Authentication error.
+    Authentication error, because token, user password not recognized
     """
     def __init__(self, message, http_code=HTTPStatus.UNAUTHORIZED):
     """
     def __init__(self, message, http_code=HTTPStatus.UNAUTHORIZED):
+        super(AuthException, self).__init__(message)
         self.http_code = http_code
         self.http_code = http_code
-        Exception.__init__(self, message)
+
+
+class AuthExceptionUnauthorized(AuthException):
+    """
+    Authentication error, because not having rights to make this operation
+    """
+    pass
 
 
 class AuthconnException(Exception):
 
 
 class AuthconnException(Exception):
@@ -25,7 +50,7 @@ class AuthconnException(Exception):
     Common and base class Exception for all authconn exceptions.
     """
     def __init__(self, message, http_code=HTTPStatus.UNAUTHORIZED):
     Common and base class Exception for all authconn exceptions.
     """
     def __init__(self, message, http_code=HTTPStatus.UNAUTHORIZED):
-        Exception.__init__(message)
+        super(AuthconnException, self).__init__(message)
         self.http_code = http_code
 
 
         self.http_code = http_code
 
 
@@ -34,7 +59,7 @@ class AuthconnConnectionException(AuthconnException):
     Connectivity error with Auth backend.
     """
     def __init__(self, message, http_code=HTTPStatus.BAD_GATEWAY):
     Connectivity error with Auth backend.
     """
     def __init__(self, message, http_code=HTTPStatus.BAD_GATEWAY):
-        AuthconnException.__init__(self, message, http_code)
+        super(AuthconnConnectionException, self).__init__(message, http_code)
 
 
 class AuthconnNotSupportedException(AuthconnException):
 
 
 class AuthconnNotSupportedException(AuthconnException):
@@ -42,7 +67,7 @@ class AuthconnNotSupportedException(AuthconnException):
     The request is not supported by the Auth backend.
     """
     def __init__(self, message, http_code=HTTPStatus.NOT_IMPLEMENTED):
     The request is not supported by the Auth backend.
     """
     def __init__(self, message, http_code=HTTPStatus.NOT_IMPLEMENTED):
-        AuthconnException.__init__(self, message, http_code)
+        super(AuthconnNotSupportedException, self).__init__(message, http_code)
 
 
 class AuthconnNotImplementedException(AuthconnException):
 
 
 class AuthconnNotImplementedException(AuthconnException):
@@ -50,7 +75,7 @@ class AuthconnNotImplementedException(AuthconnException):
     The method is not implemented by the Auth backend.
     """
     def __init__(self, message, http_code=HTTPStatus.NOT_IMPLEMENTED):
     The method is not implemented by the Auth backend.
     """
     def __init__(self, message, http_code=HTTPStatus.NOT_IMPLEMENTED):
-        AuthconnException.__init__(self, message, http_code)
+        super(AuthconnNotImplementedException, self).__init__(message, http_code)
 
 
 class AuthconnOperationException(AuthconnException):
 
 
 class AuthconnOperationException(AuthconnException):
@@ -58,7 +83,23 @@ class AuthconnOperationException(AuthconnException):
     The operation executed failed.
     """
     def __init__(self, message, http_code=HTTPStatus.INTERNAL_SERVER_ERROR):
     The operation executed failed.
     """
     def __init__(self, message, http_code=HTTPStatus.INTERNAL_SERVER_ERROR):
-        AuthconnException.__init__(self, message, http_code)
+        super(AuthconnOperationException, self).__init__(message, http_code)
+
+
+class AuthconnNotFoundException(AuthconnException):
+    """
+    The operation executed failed because element not found.
+    """
+    def __init__(self, message, http_code=HTTPStatus.NOT_FOUND):
+        super().__init__(message, http_code)
+
+
+class AuthconnConflictException(AuthconnException):
+    """
+    The operation has conflicts.
+    """
+    def __init__(self, message, http_code=HTTPStatus.CONFLICT):
+        super().__init__(message, http_code)
 
 
 class Authconn:
 
 
 class Authconn:
@@ -78,27 +119,34 @@ class Authconn:
         """
         self.config = config
 
         """
         self.config = config
 
-    def authenticate_with_user_password(self, user, password):
+    def authenticate(self, user, password, project=None, token=None):
         """
         """
-        Authenticate a user using username and password.
+        Authenticate a user using username/password or token, plus project
+        :param user: user: name, id or None
+        :param password: password or None
+        :param project: name, id, or None. If None first found project will be used to get an scope token
+        :param token: previous token to obtain authorization
+        :return: the scoped token info or raises an exception. The token is a dictionary with:
+            _id:  token string id,
+            username: username,
+            project_id: scoped_token project_id,
+            project_name: scoped_token project_name,
+            expires: epoch time when it expires,
 
 
-        :param user: username
-        :param password: password
-        :return: an unscoped token that grants access to project list
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
-    def authenticate_with_token(self, token, project=None):
-        """
-        Authenticate a user using a token. Can be used to revalidate the token
-        or to get a scoped token.
-
-        :param token: a valid token.
-        :param project: (optional) project for a scoped token.
-        :return: return a revalidated token, scoped if a project was passed or
-        the previous token was already scoped.
-        """
-        raise AuthconnNotImplementedException("Should have implemented this")
+    def authenticate_with_token(self, token, project=None):
+        """
+        Authenticate a user using a token. Can be used to revalidate the token
+        or to get a scoped token.
+    #
+        :param token: a valid token.
+        :param project: (optional) project for a scoped token.
+        :return: return a revalidated token, scoped if a project was passed or
+        the previous token was already scoped.
+        """
+        raise AuthconnNotImplementedException("Should have implemented this")
 
     def validate_token(self, token):
         """
 
     def validate_token(self, token):
         """
@@ -118,7 +166,7 @@ class Authconn:
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
-    def get_project_list(self, token):
+    def get_user_project_list(self, token):
         """
         Get all the projects associated with a user.
 
         """
         Get all the projects associated with a user.
 
@@ -127,7 +175,7 @@ class Authconn:
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
-    def get_role_list(self, token):
+    def get_user_role_list(self, token):
         """
         Get role list for a scoped project.
 
         """
         Get role list for a scoped project.
 
@@ -147,25 +195,34 @@ class Authconn:
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
-    def change_password(self, user, new_password):
+    def update_user(self, user, new_name=None, new_password=None):
         """
         """
-        Change the user password.
+        Change the user name and/or password.
 
 
-        :param user: username.
+        :param user: username or user_id
+        :param new_name: new name
         :param new_password: new password.
         :param new_password: new password.
-        :raises AuthconnOperationException: if user password change failed.
+        :raises AuthconnOperationException: if change failed.
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
-    def delete_user(self, user):
+    def delete_user(self, user_id):
         """
         Delete user.
 
         """
         Delete user.
 
-        :param user: username.
+        :param user_id: user identifier.
         :raises AuthconnOperationException: if user deletion failed.
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         :raises AuthconnOperationException: if user deletion failed.
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
+    def get_user_list(self, filter_q=None):
+        """
+        Get user list.
+
+        :param filter_q: dictionary to filter user list by name (username is also admited) and/or _id
+        :return: returns a list of users.
+        """
+
     def create_role(self, role):
         """
         Create a role.
     def create_role(self, role):
         """
         Create a role.
@@ -175,33 +232,70 @@ class Authconn:
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
-    def delete_role(self, role):
+    def delete_role(self, role_id):
         """
         Delete a role.
 
         """
         Delete a role.
 
-        :param role: role name.
+        :param role_id: role identifier.
         :raises AuthconnOperationException: if user deletion failed.
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         :raises AuthconnOperationException: if user deletion failed.
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
+    def get_role_list(self, filter_q=None):
+        """
+        Get all the roles.
+
+        :param filter_q: dictionary to filter role list by _id and/or name.
+        :return: list of roles
+        """
+        raise AuthconnNotImplementedException("Should have implemented this")
+
+    def update_role(self, role, new_name):
+        """
+        Change the name of a role
+        :param role: role name or id to be changed
+        :param new_name: new name
+        :return: None
+        """
+        raise AuthconnNotImplementedException("Should have implemented this")
+
     def create_project(self, project):
         """
         Create a project.
 
         :param project: project name.
     def create_project(self, project):
         """
         Create a project.
 
         :param project: project name.
+        :return: the internal id of the created project
         :raises AuthconnOperationException: if project creation failed.
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         :raises AuthconnOperationException: if project creation failed.
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
-    def delete_project(self, project):
+    def delete_project(self, project_id):
         """
         Delete a project.
 
         """
         Delete a project.
 
-        :param project: project name.
+        :param project_id: project identifier.
         :raises AuthconnOperationException: if project deletion failed.
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
         :raises AuthconnOperationException: if project deletion failed.
         """
         raise AuthconnNotImplementedException("Should have implemented this")
 
+    def get_project_list(self, filter_q=None):
+        """
+        Get all the projects.
+
+        :param filter_q: dictionary to filter project list, by "name" and/or "_id"
+        :return: list of projects
+        """
+        raise AuthconnNotImplementedException("Should have implemented this")
+
+    def update_project(self, project_id, new_name):
+        """
+        Change the name of a project
+        :param project_id: project to be changed
+        :param new_name: new name
+        :return: None
+        """
+        raise AuthconnNotImplementedException("Should have implemented this")
+
     def assign_role_to_user(self, user, project, role):
         """
         Assigning a role to a user in a project.
     def assign_role_to_user(self, user, project, role):
         """
         Assigning a role to a user in a project.