summaryrefslogtreecommitdiffstats
path: root/gitautodeploy/wsserver.py
blob: 1ce2e590e2ecce58224463b3e83b15a449a3b1e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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