You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							118 lines
						
					
					
						
							3.9 KiB
						
					
					
				
			
		
		
	
	
							118 lines
						
					
					
						
							3.9 KiB
						
					
					
				| from .events import SystemEvent
 | |
| 
 | |
| try:
 | |
|     from autobahn.websocket import WebSocketServerProtocol
 | |
| except ImportError:
 | |
|     WebSocketServerProtocol = object
 | |
| 
 | |
| def WebSocketClientHandlerFactory(config, clients, event_store, server_status):
 | |
|     """Factory method for webhook request handler class"""
 | |
| 
 | |
|     class WebSocketClientHandler(WebSocketServerProtocol, object):
 | |
| 
 | |
|         def __init__(self, *args, **kwargs):
 | |
|             self._config = config
 | |
|             self.clients = clients
 | |
|             self._event_store = event_store
 | |
|             self._server_status = server_status
 | |
|             import logging
 | |
|             self.logger = logging.getLogger()
 | |
|             super(WebSocketClientHandler, self).__init__(*args, **kwargs)
 | |
| 
 | |
|         def onConnect(self, request):
 | |
|             self.logger.info("Client connecting: {0}".format(request.peer))
 | |
| 
 | |
|             # Web UI needs to be enabled
 | |
|             if not self.validate_web_ui_enabled():
 | |
|                 return
 | |
| 
 | |
|             # Client needs to be whitelisted
 | |
|             if not self.validate_web_ui_whitelist():
 | |
|                 return
 | |
| 
 | |
|         def onOpen(self):
 | |
|             self.logger.info("WebSocket connection open.")
 | |
| 
 | |
|         def onMessage(self, payload, isBinary):
 | |
|             import json
 | |
| 
 | |
|             if isBinary:
 | |
|                 return
 | |
| 
 | |
|             try:
 | |
|                 data = json.loads(payload)
 | |
| 
 | |
|                 # Handle authentication requests
 | |
|                 if 'type' in data and data['type'] == 'authenticate':
 | |
| 
 | |
|                     # Verify auth key
 | |
|                     if 'auth-key' in data and data['auth-key'] == self._server_status['auth-key']:
 | |
|                         self.clients.append(self)
 | |
| 
 | |
|                         # Let the client know that they are authenticated
 | |
|                         self.sendMessage(json.dumps({
 | |
|                             "type": "authenticated"
 | |
|                         }))
 | |
|                         return
 | |
| 
 | |
|                     else:
 | |
|                         self.logger.error("Recieved bad auth key.")
 | |
| 
 | |
|                         self.sendMessage(json.dumps({
 | |
|                             "type": "bad-auth-key"
 | |
|                         }))
 | |
|                         return
 | |
| 
 | |
|             except Exception as e:
 | |
| 
 | |
|                 self.logger.error("Unable to interpret incoming message: %s" % e)
 | |
| 
 | |
|             if self not in self.clients:
 | |
|                 self.logger.error("Recieved message form unauthenticated client, closing connection.")
 | |
|                 self.sendClose()
 | |
|                 return
 | |
| 
 | |
|             #self.logger.info("WebSocket connection open.")
 | |
|             #if isBinary:
 | |
|             #    self.logger.info("Binary message received: {0} bytes".format(len(payload)))
 | |
|             #else:
 | |
|             #    self.logger.info("Text message received: {0}".format(payload.decode('utf8')))
 | |
| 
 | |
|             #for client in self.clients:
 | |
|             #    client.sendMessage(payload, isBinary)
 | |
| 
 | |
|             # echo back message verbatim
 | |
|             #self.sendMessage(payload, isBinary)
 | |
| 
 | |
|         def onClose(self, wasClean, code, reason):
 | |
|             self.logger.info("WebSocket connection closed: {0}".format(reason))
 | |
| 
 | |
|             if self in self.clients:
 | |
|                 self.clients.remove(self)
 | |
| 
 | |
|         def validate_web_ui_enabled(self):
 | |
|             """Verify that the Web UI is enabled"""
 | |
| 
 | |
|             if self._config['web-ui-enabled']:
 | |
|                 return True
 | |
| 
 | |
|             self.sendClose()
 | |
|             return False
 | |
| 
 | |
|         def validate_web_ui_whitelist(self):
 | |
|             """Verify that the client address is whitelisted"""
 | |
| 
 | |
|             # Allow all if whitelist is empty
 | |
|             if len(self._config['web-ui-whitelist']) == 0:
 | |
|                 return True
 | |
| 
 | |
|             # Verify that client IP is whitelisted
 | |
|             if self.peer.host in self._config['web-ui-whitelist']:
 | |
|                 return True
 | |
| 
 | |
|             self.sendClose()
 | |
|             logger.info("Unautorized connection attempt from %s" % self.peer.host)
 | |
|             return False
 | |
| 
 | |
|     return WebSocketClientHandler
 |