blob: eaa9f96ae82d370cf62d0e9c0a13a051ebee1c51 [file] [log] [blame]
#// 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