diff --git a/Dockerfile b/Dockerfile index cdf7bf7..7067a7b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,6 +25,8 @@ RUN curl -L https://raw.githubusercontent.com/pyenv/pyenv-installer/master/bin/p ENV TFW_APP_DIR="/srv/app" COPY src/app ${TFW_APP_DIR} +ENV TFW_LOGIN_APP_DIR="/tmp/source_code_server" +ENV TFW_LOGIN_APP_PORT=6666 ENV TFW_EVENT_HANDLERS_DIR="/opt/event_handlers" COPY src/event_handlers ${TFW_EVENT_HANDLERS_DIR} diff --git a/lib/config/envvars.py b/lib/config/envvars.py index 6f997d8..19c27b8 100644 --- a/lib/config/envvars.py +++ b/lib/config/envvars.py @@ -4,5 +4,8 @@ PUBLISHER_PORT = os.getenv('PUBLISHER_PORT', 7654) RECEIVER_PORT = os.getenv('RECEIVER_PORT', 8765) WEB_PORT = os.getenv('WEB_PORT', 4242) SUPERVISOR_HTTP_PORT = os.getenv('TFW_SUPERVISOR_PORT', 9001) +LOGIN_APP_PORT= os.getenv('TFW_LOGIN_APP_PORT', 6666) SUPERVISOR_HTTP_URI = 'http://localhost:{}'.format(SUPERVISOR_HTTP_PORT) + +LOGIN_APP_DIR = os.getenv('TFW_LOGIN_APP_DIR') diff --git a/src/event_handlers/source_code_event_handler.py b/src/event_handlers/source_code_event_handler.py new file mode 100644 index 0000000..9f39931 --- /dev/null +++ b/src/event_handlers/source_code_event_handler.py @@ -0,0 +1,67 @@ +import json +from shutil import copy, rmtree, copytree +from os.path import splitext +import xmlrpc.client + +from config import SUPERVISOR_HTTP_URI, LOGIN_APP_DIR +from event_handler_base import EventHandlerBase + + +class SourceCodeEventHandler(EventHandlerBase): + def __init__(self, anchor, filename, process_name=None, zmq_context=None): + super().__init__(anchor, zmq_context) + self.working_directory = LOGIN_APP_DIR + self.filename = filename + self.language = map_file_extension_to_language(filename) + self.process_name = process_name or splitext(filename)[0] + + server = xmlrpc.client.ServerProxy(SUPERVISOR_HTTP_URI) + self.supervisor = server.supervisor + + self.file = self.create_initial_state() + + def event_handler_callback(msg_parts): + anchor, message = msg_parts + message_json = json.loads(message) + data = message_json['data'] + if anchor == b'reset': + self.file = self.create_initial_state(process_is_running=True) + if data['command'] == 'read': + with open(self.file, 'r') as ifile: + content = ifile.read() + message_json['data'] = { + 'filename': self.filename, + 'content': content, + 'language': self.language + } + encoded_response = json.dumps(message_json).encode('utf-8') + self.zmq_push_socket.send_multipart([anchor, encoded_response]) + elif data['command'] == 'write': + with open(self.file, 'w') as ofile: + ofile.write(data['content']) + self.supervisor.stopProcess(self.process_name) + self.supervisor.startProcess(self.process_name) + + self.zmq_sub_stream.on_recv(event_handler_callback) + + def create_initial_state(self, process_is_running=False): + if process_is_running: + self.supervisor.stopProcess(self.process_name) + + rmtree(self.working_directory, ignore_errors=True) + copytree('source_code_server/', self.working_directory) + file = copy(self.filename, self.working_directory) + + self.supervisor.startProcess(self.process_name) + + return file + + +def map_file_extension_to_language(filename): + language_map = { + # TODO: extend, maybe auto-generate??? + '.py': 'python', + '.js': 'javascript' + } + _, extension = splitext(filename) + return language_map[extension] diff --git a/src/event_handlers/source_code_server/server.py b/src/event_handlers/source_code_server/server.py new file mode 100644 index 0000000..83db5d6 --- /dev/null +++ b/src/event_handlers/source_code_server/server.py @@ -0,0 +1,26 @@ +import json + +from tornado.ioloop import IOLoop +from tornado.web import RequestHandler, Application + +from config import LOGIN_APP_PORT +from login_component import authorize_login + + +class LoginHandler(RequestHandler): + def post(self, *args, **kwargs): + request = json.loads(self.request.body) + email, is_admin = authorize_login( + request['email'], + request['password'] + ) + self.write({ + 'email': email, + 'is_admin': is_admin + }) + + +if __name__ == '__main__': + application = Application([(r'/login', LoginHandler)]) + application.listen(LOGIN_APP_PORT) + IOLoop.instance().start() diff --git a/src/event_handlers/source_code_server/users.db b/src/event_handlers/source_code_server/users.db new file mode 100644 index 0000000..cde24ab Binary files /dev/null and b/src/event_handlers/source_code_server/users.db differ diff --git a/supervisord.conf b/supervisord.conf index ca03c25..09b759c 100644 --- a/supervisord.conf +++ b/supervisord.conf @@ -23,3 +23,8 @@ command=env python app.py [program:event_handler_main] directory=%(ENV_TFW_EVENT_HANDLERS_DIR)s command=env python event_handler_main.py + +[program:login] +directory=%(ENV_TFW_LOGIN_APP_DIR)s +command=env python server.py +autostart=false