| #// Copyright (c) 2000-2017 Ericsson Telecom AB // |
| #// All rights reserved. This program and the accompanying materials are made available under the terms // |
| #// of the Eclipse Public License v1.0 which accompanies this distribution, and is available at // |
| #// http://www.eclipse.org/legal/epl-v10.html // |
| #///////////////////////////////////////////////////////////////////////////////////////////////////////// |
| import json, uuid, logging |
| from Common.DsRestAPI import DsRestAPI |
| from LdapAuthenticator import authenticate |
| from FileUserHandler import FileUserHandler as UserHandler |
| from Help import DSHELP |
| |
| class AuthenticationHandler: |
| ''' |
| This class handles the authentication and user groups |
| Requests coming to login/api.authenticate are used for logging in. |
| Requests coming to logout/api.authenticate are used for logging out. |
| DsRestAPI requests can be used to edit the user groups. |
| AppAgent can use the getUserCredentials public function to get the user credentials of the current user. |
| ''' |
| |
| SOURCE_ID = 'Authentication' |
| |
| def __init__(self, directory): |
| self._sessionDb = {} |
| self._userHandler = UserHandler(directory) |
| self._logger = logging.getLogger(__name__) |
| self._dsRestAPI = DsRestAPI(self._getDataHandler, self._setDataHandler) |
| |
| def _login(self, body): |
| authenticate(body['username'], body['password']) |
| sessionId = str(uuid.uuid4()) |
| groups = self._userHandler.getUserGroups(body['username']) |
| self._sessionDb[sessionId] = {'username': body['username'], 'password': body['password'], 'groups': groups} |
| return sessionId |
| |
| def _getSessionIdFromHeaders(self, headers): |
| cookieHeader = headers.get('cookie') |
| sessionId = None |
| if cookieHeader != None: |
| for cookie in cookieHeader.split(';'): |
| if cookie.strip().startswith('PYSESSID='): |
| sessionId = cookie.strip().replace('PYSESSID=', '') |
| break |
| return sessionId |
| |
| def getUserCredentials(self, headers): |
| sessionId = self._getSessionIdFromHeaders(headers) |
| if sessionId in self._sessionDb: |
| return self._sessionDb[sessionId] |
| else: |
| return {'username': None, 'password': None, 'groups': set([])} |
| |
| def _getDataHandler(self, request, userCredentials): |
| element = request['element'] |
| params = request['params'] |
| |
| if element == 'help': |
| help = {'sources': [{'source': self.SOURCE_ID, 'dataElements': DSHELP}]} |
| return {'node': {'val': json.dumps(help).encode('hex'), 'tp': 5}} |
| elif element == 'ListGroups': |
| return {'list': [{'node': {'val': group, 'tp': 10}} for group in self._userHandler.listGroups()]} |
| elif element == 'ListUsersInGroup' and len(params) == 1 and params[0]['paramName'] == 'Group': |
| return {'list': [{'node': {'val': user, 'tp': 10}} for user in self._userHandler.listUsersInGroup(params[0]['paramValue'])]} |
| elif element == 'ListGroupsOfUser' and len(params) == 1 and params[0]['paramName'] == 'User': |
| return {'list': [{'node': {'val': group, 'tp': 10}} for group in self._userHandler.getUserGroups(params[0]['paramValue'])]} |
| elif element in ['RemoveGroup', 'RemoveUserFromGroup']: |
| return {'node': {'val': '0', 'tp': 1}} |
| elif element in ['AddGroup', 'AddUserToGroup']: |
| return {'node': {'val': '0', 'tp': 4}} |
| |
| def _setDataHandler(self, request, userCredentials): |
| element = request['element'] |
| params = request['params'] |
| content = request['content'] |
| tp = request['tp'] |
| |
| if 'admin' in userCredentials['groups']: |
| if element == 'AddGroup': |
| self._userHandler.addGroup(content) |
| return {'node': {'val': content, 'tp': tp}} |
| elif element == 'RemoveGroup' and len(params) == 1 and params[0]['paramName'] == 'Group': |
| self._userHandler.removeGroup(params[0]['paramValue']) |
| return {'node': {'val': '0', 'tp': 1}} |
| elif element == 'AddUserToGroup' and len(params) == 1 and params[0]['paramName'] == 'Group': |
| self._userHandler.addUserToGroup(content, params[0]['paramValue']) |
| return {'node': {'val': content, 'tp': tp}} |
| elif element == 'RemoveUserFromGroup' and len(params) == 2 and params[0]['paramName'] == 'User' and params[1]['paramName'] == 'Group': |
| self._userHandler.removeUserFromGroup(params[0]['paramValue'], params[1]['paramValue']) |
| return {'node': {'val': '0', 'tp': 1}} |
| |
| def handleMessage(self, method, path, headers, body, userCredentials, response): |
| if path.startswith('login'): |
| try: |
| loginInfo = json.loads(body) |
| sessionId = self._login(loginInfo) |
| response['returnCode'] = 200 |
| # increase the year when needed |
| response['headers']['Set-Cookie'] = 'PYSESSID=' + sessionId + '; Path=/; expires=Thu, 01 Jan 2070 00:00:00 UTC;' |
| self._logger.info('Login ' + sessionId + ' ' + loginInfo['username']) |
| except Exception as e: |
| self._logger.exception('Failed to login') |
| response['returnCode'] = 401 |
| response['body'] = str(e) |
| elif path.startswith('logout'): |
| try: |
| sessionId = self._getSessionIdFromHeaders(headers) |
| self._sessionDb.pop(sessionId, None) |
| response['returnCode'] = 200 |
| response['headers']['Set-Cookie'] = 'PYSESSID=' + '; Path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC;' |
| self._logger.info('Logout ' + sessionId + ' ' + str(userCredentials['username'])) |
| except Exception as e: |
| self._logger.exception('Failed to logout ' + str(userCredentials['username'])) |
| response['returnCode'] = 400 |
| response['body'] = str(e) |
| else: |
| response['body'] = json.dumps(self._dsRestAPI.parseRequest(json.loads(body), userCredentials)) |
| response['headers']['Content-Type'] = 'application/json' |
| |
| def getDataSourceHandlers(self): |
| return { |
| self.SOURCE_ID: { |
| 'getDataHandler': self._getDataHandler, |
| 'setDataHandler': self._setDataHandler |
| } |
| } |
| |
| def close(self): |
| pass |